谷粒学院——Day18【权限管理Spring Security、配置中心Nacos、代码托管git】

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云解析 DNS,旗舰版 1个月
简介: 谷粒学院——Day18【权限管理Spring Security、配置中心Nacos、代码托管git】
❤ 作者主页:欢迎来到我的技术博客😎
❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉

整合Spring Security

一、Spring Security介绍

1. 框架介绍

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。

一般来说,Web 应用的安全性包括用户认证(Authentication)用户授权(Authorization) 两个部分。

(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。

(2)用户授权指的是: 验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

Spring Security其实就是用filter,多请求的路径进行过滤。
(1)如果是基于Session,那么Spring-security会对cookie里的sessionid进行解析,找到服务器存储的sesion信息,然后判断当前用户是否符合请求的要求。

(2)如果是token,则是解析出token,然后将当前请求加入到Spring-security管理的权限信息中去。
 

2. 认证与授权实现思路

如果系统的模块众多,每个模块都需要就行授权与认证,所以我们选择基于token的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为key,权限列表为value的形式存入redis缓存中,根据用户名相关信息生成token返回,浏览器将token记录到cookie中,每次调用api接口都默认将token携带到header请求头中,Spring-security解析header头获取token信息,解析token获取当前用户名,根据用户名就可以从redis中获取权限列表,这样Spring-security就能够判断当前请求是否有权限访问。

二、整合Spring Security

1. 在common下创建spring_security模块

在这里插入图片描述

 

2. 在spring_security引入相关依赖

<dependencies>
        <dependency>
            <groupId>com.atguigu</groupId>
            <artifactId>common_utils</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- Spring Security依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
    </dependencies>

3. 在service_acl引入spring_security依赖


<dependency>
    <groupId>com.atguigu</groupId>
    <artifactId>spring_security</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

4. 代码结构说明

在这里插入图片描述
 

5. 创建spring security核心配置类

Spring Security 的核心配置就是继承 WebSecurityConfigurerAdapter 并注解 @EnableWebSecurity 的配置。

这个配置指明了用户名密码的处理方式、请求路径的开合、登录登出控制等和安全相关的配置。

package com.atguigu.serurity.config;

import com.atguigu.serurity.filter.TokenAuthenticationFilter;
import com.atguigu.serurity.filter.TokenLoginFilter;
import com.atguigu.serurity.security.DefaultPasswordEncoder;
import com.atguigu.serurity.security.TokenLogoutHandler;
import com.atguigu.serurity.security.TokenManager;
import com.atguigu.serurity.security.UnauthorizedEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * <p>
 * Security配置类
 * </p>
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {

    private UserDetailsService userDetailsService;
    private TokenManager tokenManager;
    private DefaultPasswordEncoder defaultPasswordEncoder;
    private RedisTemplate redisTemplate;

    @Autowired
    public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
                                  TokenManager tokenManager, RedisTemplate redisTemplate) {
        this.userDetailsService = userDetailsService;
        this.defaultPasswordEncoder = defaultPasswordEncoder;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 配置设置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint())
                .and().csrf().disable()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and().logout().logoutUrl("/admin/acl/index/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();
    }

    /**
     * 密码处理
     * @param auth
     * @throws Exception
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
    }

    /**
     * 配置哪些请求不拦截
     * @param web
     */
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/api/**",
                "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"
               );
    }
}

6. 创建认证授权相关的工具类

  1. DefaultPasswordEncoder:密码处理的方法

    package com.atguigu.serurity.security;
    
    import com.atguigu.commonutils.MD5;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Component;
    
    /**
     * <p>
     * t密码的处理方法类型
     * </p>
     */
    @Component
    public class DefaultPasswordEncoder implements PasswordEncoder {
    
        public DefaultPasswordEncoder() {
            this(-1);
        }
    
        /**
         * @param strength
         *            the log rounds to use, between 4 and 31
         */
        public DefaultPasswordEncoder(int strength) {
    
        }
    
        public String encode(CharSequence rawPassword) {
            return MD5.encrypt(rawPassword.toString());
        }
    
        public boolean matches(CharSequence rawPassword, String encodedPassword) {
            return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));
        }
    }
  2. TokenManager:token操作的工具类

    package com.atguigu.serurity.security;
    
    import com.atguigu.commonutils.R;
    import com.atguigu.commonutils.ResponseUtil;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.logout.LogoutHandler;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * <p>
     * 登出业务逻辑类
     * </p>
     */
    public class TokenLogoutHandler implements LogoutHandler {
    
        private TokenManager tokenManager;
        private RedisTemplate redisTemplate;
    
        public TokenLogoutHandler(TokenManager tokenManager, RedisTemplate redisTemplate) {
            this.tokenManager = tokenManager;
            this.redisTemplate = redisTemplate;
        }
    
        @Override
        public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
            String token = request.getHeader("token");
            if (token != null) {
                tokenManager.removeToken(token);
    
                //清空当前用户缓存中的权限数据
                String userName = tokenManager.getUserFromToken(token);
                redisTemplate.delete(userName);
            }
            ResponseUtil.out(response, R.ok());
        }
    
    }
  3. TokenLogoutHandler:退出实现

    package com.atguigu.serurity.security;
    
    import io.jsonwebtoken.CompressionCodecs;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    /**
     * <p>
     * token管理
     * </p>
     */
    @Component
    public class TokenManager {
    
        private long tokenExpiration = 24*60*60*1000;
        private String tokenSignKey = "123456";
    
        public String createToken(String username) {
            String token = Jwts.builder().setSubject(username)
                    .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                    .signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();
            return token;
        }
    
        public String getUserFromToken(String token) {
            String user = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject();
            return user;
        }
    
        public void removeToken(String token) {
            //jwttoken无需删除,客户端扔掉即可。
        }
    
    }
    
  4. UnauthorizedEntryPoint:未授权统一处理

    package com.atguigu.serurity.security;
    
    import com.atguigu.commonutils.R;
    import com.atguigu.commonutils.ResponseUtil;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.AuthenticationEntryPoint;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * <p>
     * 未授权的统一处理方式
     * </p>
     */
    public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                             AuthenticationException authException) throws IOException, ServletException {
    
            ResponseUtil.out(response, R.error());
        }
    }
    

7. 创建认证授权实体类

  • SecutityUser

    package com.atguigu.serurity.entity;
    
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.util.StringUtils;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    /**
     * <p>
     * 安全认证用户详情信息
     * </p>
     */
    @Data
    @Slf4j
    public class SecurityUser implements UserDetails {
    
        //当前登录用户
        private transient User currentUserInfo;
    
        //当前权限
        private List<String> permissionValueList;
    
        public SecurityUser() {
        }
    
        public SecurityUser(User user) {
            if (user != null) {
                this.currentUserInfo = user;
            }
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            for(String permissionValue : permissionValueList) {
                if(StringUtils.isEmpty(permissionValue)) continue;
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                authorities.add(authority);
            }
    
            return authorities;
        }
    
        @Override
        public String getPassword() {
            return currentUserInfo.getPassword();
        }
    
        @Override
        public String getUsername() {
            return currentUserInfo.getUsername();
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    
  • user

    package com.atguigu.serurity.entity;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * <p>
     * 用户实体类
     * </p>
     */
    @Data
    @ApiModel(description = "用户实体类")
    public class User implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty(value = "微信openid")
        private String username;
    
        @ApiModelProperty(value = "密码")
        private String password;
    
        @ApiModelProperty(value = "昵称")
        private String nickName;
    
        @ApiModelProperty(value = "用户头像")
        private String salt;
    
        @ApiModelProperty(value = "用户签名")
        private String token;
    
    }

8. 创建认证和授权的filter

  1. TokenLoginFilter:认证的filter

    package com.atguigu.serurity.filter;
    
    import com.atguigu.commonutils.R;
    import com.atguigu.commonutils.ResponseUtil;
    import com.atguigu.serurity.entity.SecurityUser;
    import com.atguigu.serurity.entity.User;
    import com.atguigu.serurity.security.TokenManager;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    
    /**
     * <p>
     * 登录过滤器,继承UsernamePasswordAuthenticationFilter,对用户名密码进行登录校验
     * </p>
     */
    public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    
        private AuthenticationManager authenticationManager;
        private TokenManager tokenManager;
        private RedisTemplate redisTemplate;
    
        public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
            this.authenticationManager = authenticationManager;
            this.tokenManager = tokenManager;
            this.redisTemplate = redisTemplate;
            this.setPostOnly(false);
            this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login","POST"));
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
                throws AuthenticationException {
            try {
                User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
    
                return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
        }
    
        /**
         * 登录成功
         * @param req
         * @param res
         * @param chain
         * @param auth
         * @throws IOException
         * @throws ServletException
         */
        @Override
        protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
                                                Authentication auth) throws IOException, ServletException {
            SecurityUser user = (SecurityUser) auth.getPrincipal();
            String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
            redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
    
            ResponseUtil.out(res, R.ok().data("token", token));
        }
    
        /**
         * 登录失败
         * @param request
         * @param response
         * @param e
         * @throws IOException
         * @throws ServletException
         */
        @Override
        protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                                  AuthenticationException e) throws IOException, ServletException {
            ResponseUtil.out(response, R.error());
        }
    }
    
  2. TokenAuthenticationFilter:授权filter

    package com.atguigu.serurity.filter;
    
    import com.atguigu.commonutils.R;
    import com.atguigu.commonutils.ResponseUtil;
    import com.atguigu.serurity.security.TokenManager;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    /**
     * <p>
     * 访问过滤器
     * </p>
     */
    public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
        private TokenManager tokenManager;
        private RedisTemplate redisTemplate;
    
        public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
            super(authManager);
            this.tokenManager = tokenManager;
            this.redisTemplate = redisTemplate;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
                throws IOException, ServletException {
            logger.info("================="+req.getRequestURI());
            if(req.getRequestURI().indexOf("admin") == -1) {
                chain.doFilter(req, res);
                return;
            }
    
            UsernamePasswordAuthenticationToken authentication = null;
            try {
                authentication = getAuthentication(req);
            } catch (Exception e) {
                ResponseUtil.out(res, R.error());
            }
    
            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                ResponseUtil.out(res, R.error());
            }
            chain.doFilter(req, res);
        }
    
        private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
            // token置于header里
            String token = request.getHeader("token");
            if (token != null && !"".equals(token.trim())) {
                String userName = tokenManager.getUserFromToken(token);
    
                List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
                Collection<GrantedAuthority> authorities = new ArrayList<>();
                for(String permissionValue : permissionValueList) {
                    if(StringUtils.isEmpty(permissionValue)) continue;
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                    authorities.add(authority);
                }
    
                if (!StringUtils.isEmpty(userName)) {
                    return new UsernamePasswordAuthenticationToken(userName, token, authorities);
                }
                return null;
            }
            return null;
        }
    }

创建查询用户类和前端对接

一、创建自定义查询用户类

在service_acl模块创建,因为其他模板不会用到:
在这里插入图片描述
 
UserDetailsServiceImpl

package com.atguigu.aclservice.service.impl;

import com.atguigu.aclservice.entity.User;
import com.atguigu.aclservice.service.PermissionService;
import com.atguigu.aclservice.service.UserService;
import com.atguigu.serurity.entity.SecurityUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;


/**
 * <p>
 * 自定义userDetailsService - 认证用户详情
 * </p>
 */
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private PermissionService permissionService;

    /***
     * 根据账号获取用户信息
     * @param username:
     * @return: org.springframework.security.core.userdetails.UserDetails
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库中取出用户信息
        User user = userService.selectByUsername(username);

        // 判断用户是否存在
        if (null == user){
            //throw new UsernameNotFoundException("用户名不存在!");
        }
        // 返回UserDetails实现类
        com.atguigu.serurity.entity.User curUser = new com.atguigu.serurity.entity.User();
        BeanUtils.copyProperties(user,curUser);

        List<String> authorities = permissionService.selectPermissionValueByUserId(user.getId());
        SecurityUser securityUser = new SecurityUser(curUser);
        securityUser.setPermissionValueList(authorities);
        return securityUser;
    }

}

二、后端接口和前端页面对接

1. 在前端项目中下载依赖

npm install --save vuex-persistedstate

2. 替换相关文件

在这里插入图片描述
 

3. 在node_modules文件夹中替换element-ui依赖

在这里插入图片描述
 


Nacos配置中心

一、配置中心介绍

1. Spring Cloud Config

Spring Cloud Config 为分布式系统的外部配置提供了服务端和客户端的支持方案。在配置的服务端您可以在所有环境中为应用程序管理外部属性的中心位置。客户端和服务端概念上的Spring Environment 和 PropertySource 抽象保持同步, 它们非常适合Spring应用程序,但是可以与任何语言中运行的应用程序一起使用。当应用程序在部署管道中从一个开发到测试直至进入生产时,您可以管理这些环境之间的配置,并确保应用程序在迁移时具有它们需要运行的所有内容。服务器存储后端的默认实现使用git,因此它很容易支持标记版本的配置环境,并且能够被管理内容的各种工具访问。很容易添加替代的实现,并用Spring配置将它们插入。
Spring Cloud Config 包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git。

2. Nacos替换Config

Nacos 可以与 Spring, Spring Boot, Spring Cloud 集成,并能代替 Spring Cloud Eureka, Spring Cloud Config。
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更。

应用场景:
在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成。配置变更是调整系统运行时的行为的有效手段。

如果微服务架构中没有使用统一配置中心时,所存在的问题:

  • 配置文件分散在各个项目里,不方便维护。
  • 配置内容安全与权限。
  • 更新配置后,项目需要重启。

nacos配置中心:系统配置的集中管理(编辑、存储、分发)、动态更新不重启、回滚配置(变更管理、历史版本管理、变更审计)等所有与配置相关的活动。


二、读取Nacos配置中心的配置文件

1. 在Nacos创建统一配置文件

(1)点击创建按钮

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/e35f723da42f4c0989b35b2f0383232f.png)
&nbsp;

(2) 输入配置信息
在这里插入图片描述
 

(3) Data ID 的完整规则格式如下:
${prefix}-${spring.profile.active}.${file-extension}

  • prefix 默认为所属工程配置spring.application.name 的值(即:nacos-provider),也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profiles.active=dev 即为当前环境对应的 profile。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。

2. 以service-statistics模块为例

(1)在service中引入依赖

     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

(2)创建bootstrap.properties配置文件


#配置中心地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

#spring.profiles.active=dev

# 该配置影响统一配置中心中的dataId
spring.application.name=service-statistics

(3)把项目之前的application.properties内容注释,启动项目查看效果


3. 补充:springboot配置文件加载顺序

其实yml和properties文件是一样的原理,且一个项目上要么yml或者properties,二选一的存在。推荐使用yml,更简洁。

bootstrapapplication :
(1)加载顺序
这里主要是说明application和bootstrap的加载顺序。

  • bootstrap.yml(bootstrap.properties)先加载。
  • application.yml(application.properties)后加载。
  • bootstrap.yml 用于应用程序上下文的引导阶段。
  • bootstrap.yml 由父Spring ApplicationContext加载。
  • 父ApplicationContext 被加载到使用 application.yml 的之前。

(2)配置区别

  • bootstrap.yml 和application.yml 都可以用来配置参数。
  • bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
  • application.yml 可以用来定义应用级别的。

三、名称空间切换环境

在实际开发中,通常有多套不同的环境(默认只有public),那么这个时候可以根据指定的环境来创建不同的 namespce,例如,开发、测试和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。以此来实现多环境的隔离。

1. 创建命名空间

在这里插入图片描述
 
默认只有public,新建了dev、test和prod命名空间
在这里插入图片描述
 

2. 克隆配置

切换到配置列表:
在这里插入图片描述
 
可以发现有四个名称空间public(默认)以及我们自己添加的3个名称空间(prod、dev、test),可以点击查看每个名称空间下的配置文件,当然现在只有public下有一个配置。

默认情况下,项目会到public下找 服务名.properties文件

接下来,在dev名称空间中也添加一个nacos-provider.properties配置。这时有两种方式:

  • 第一,切换到dev名称空间,添加一个新的配置文件。缺点:每个环境都要重复配置类似的项目。
  • 第二,直接通过clone方式添加配置,并修改即可。推荐。

在这里插入图片描述
 
点击编辑:修改配置内容,端口号改为8013以作区分
在这里插入图片描述
 
在项目模块中,修改bootstrap.properties添加如下配置:

spring.cloud.nacos.config.server-addr=127.0.0.1:8848

spring.profiles.active=dev

# 该配置影响统一配置中心中的dataId,之前已经配置过
spring.application.name=service-statistics

spring.cloud.nacos.config.namespace=13b5c197-de5b-47e7-9903-ec0538c9db01

namespace的值为:
在这里插入图片描述
 
重启服务提供方服务,测试修改之后是否生效。


四、多配置文件加载

在一些情况下需要加载多个配置文件。假如现在dev名称空间下有三个配置文件:service-statistics.properties、redis.properties、jdbc.properties
在这里插入图片描述
 
添加配置,加载多个配置文件:

spring.cloud.nacos.config.server-addr=127.0.0.1:8848

spring.profiles.active=dev

# 该配置影响统一配置中心中的dataId,之前已经配置过
spring.application.name=service-statistics

spring.cloud.nacos.config.namespace=13b5c197-de5b-47e7-9903-ec0538c9db01

spring.cloud.nacos.config.ext-config[0].data-id=redis.properties

# 开启动态刷新配置,否则配置文件修改,工程无法感知
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=jdbc.properties
spring.cloud.nacos.config.ext-config[1].refresh=true

提交代码到远程Git仓库

码云:https://gitee.com

  1. 通过网站右上角的「+」号,选择「新建仓库」,进入新建仓库页面

在这里插入图片描述
 

  1. 新建仓库

在这里插入图片描述
 

  1. 打开项目并点击菜单栏上的【CVS】--》【Create Git Repository】创建本地仓库

在这里插入图片描述
 

  1. 在打开的【Create Git Repository】对话框内选择本地仓库的位置,这里选择项目的根目录

在这里插入图片描述
 

  1. 右击项目点击【Git】--》【Add】,接着点击【Git】--》【Commit Directory】在打开的窗口中选择要上传到本地仓库的代码并添加注释后提交到本地仓库内

在这里插入图片描述
 

  1. 右击项目点击【Git】--》【Repository】--》【Remotes...】。在打开的【Git Remotes】窗口中添加码云的远程仓库。码云的远程仓库地址可以在码云仓库内找到。

在这里插入图片描述
在这里插入图片描述

 

  1. 上传代码到码云,右击项目点击【Git】--》【Repository】--》【Push...】在打开的【Push commits】内可以看到已提交到本地仓库的提交信息。点击【Push】按钮将本地仓库的代码上传到码云上,上传成功后就可以在码云上看到了

在这里插入图片描述
 
在这里插入图片描述


创作不易,如果有帮助到你,请给文章==点个赞和收藏==,让更多的人看到!!!
==关注博主==不迷路,内容持续更新中。

目录
相关文章
|
3月前
|
Cloud Native Java Nacos
微服务时代的新宠儿!Spring Cloud Nacos实战指南,带你玩转服务发现与配置管理,拥抱云原生潮流!
【8月更文挑战第29天】Spring Cloud Nacos作为微服务架构中的新兴之星,凭借其轻量、高效的特点,迅速成为服务发现、配置管理和治理的首选方案。Nacos(命名和配置服务)由阿里巴巴开源,为云原生应用提供了动态服务发现及配置管理等功能,简化了服务间的调用与依赖管理。本文将指导你通过五个步骤在Spring Boot项目中集成Nacos,实现服务注册、发现及配置动态管理,从而轻松搭建出高效的微服务环境。
246 0
|
3天前
|
负载均衡 应用服务中间件 Nacos
Nacos配置中心
Nacos配置中心
19 1
Nacos配置中心
|
3天前
|
网络安全 Nacos 开发者
Nacos作为流行的微服务注册与配置中心,“节点提示暂时不可用”是常见的问题之一
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,“节点提示暂时不可用”是常见的问题之一。本文将探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务的正常运行。通过检查服务实例状态、网络连接、Nacos配置、调整健康检查策略等步骤,可以有效解决这一问题。
12 4
|
3天前
|
Java 网络安全 Nacos
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,实际使用中常遇到“客户端不发送心跳检测”的问题。本文深入探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务正常运行。通过检查客户端配置、网络连接、日志、版本兼容性、心跳策略、注册状态、重启应用和环境变量等步骤,系统地排查和解决这一问题。
12 3
|
3天前
|
安全 Nacos 数据库
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改。本文详细探讨了这一问题的原因及解决方案,包括限制公网访问、使用HTTPS、强化数据库安全、启用访问控制、监控和审计等步骤,帮助开发者确保服务的安全运行。
12 3
|
11天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
35 0
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
3月前
|
安全 Nacos 数据安全/隐私保护
升级指南:从Nacos 1.3.0 到 2.3.0,并兼容 Seata 的鉴权配置
本文详细介绍了如何在微服务环境下从 Nacos 1.3.0 升级到 2.3.0,并确保 Seata 各版本的兼容性。作者小米分享了升级过程中的关键步骤,包括备份配置、更新鉴权信息及验证测试等,并解答了常见问题。通过这些步骤,可以帮助读者顺利完成升级并提高系统的安全性与一致性。
115 8
升级指南:从Nacos 1.3.0 到 2.3.0,并兼容 Seata 的鉴权配置
|
3月前
|
Cloud Native Java Nacos
Spring Cloud Config、Apollo、Nacos和Archaius对比
这篇文章对比了Spring Cloud Config、Apollo、Nacos和Archaius这四种配置中心的适应场景、优缺点。文中讨论了它们的功能特点,例如Spring Cloud Config的集中化配置管理和动态刷新能力,Apollo的实时配置推送和权限治理,Nacos的服务发现和管理功能,以及Archaius的动态配置更新能力。文章指出选择配置中心应根据项目需求和架构来决定,并提供了一个对比图来帮助读者更直观地理解这些工具的差异。
80 1
Spring Cloud Config、Apollo、Nacos和Archaius对比
|
3月前
|
运维 Java Nacos
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心