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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容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】按钮将本地仓库的代码上传到码云上,上传成功后就可以在码云上看到了

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


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

目录
相关文章
|
11天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
31 2
|
17天前
|
算法 网络安全 开发工具
[Git]关联远程库的两种方法及配置
本文介绍了 git 的四种连接方式:ssh 连接、HTTPS 连接、SVN 连接和 SVN + ssh 连接,重点讲解了 HTTPS 和 ssh 连接方式的配置及注意事项。文章详细解释了 HTTPS 连接的身份验证过程、常见问题及解决方案,以及 ssh 连接的公钥和私钥的创建、配置方法。此外,还介绍了如何在同一台电脑上连接多个 gitee 账号的方法。
54 0
[Git]关联远程库的两种方法及配置
|
1月前
|
开发工具 git
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
38 1
|
2月前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
2月前
|
网络协议 开发工具 网络虚拟化
SourceTree git 配置代理
SourceTree git 配置代理
69 1
|
1月前
|
编译器 网络安全 开发工具
git学习五:切换本地仓库出现的问题。修改git配置初始化。error:src refspec master does not match any。错误总结,送上几个案例
这篇文章是关于Git使用中遇到的一些问题及其解决方案的总结,包括切换本地仓库时的问题、修改Git初始化配置、以及解决"error: src refspec master does not match any"错误等。
54 0
|
2月前
|
存储 Shell 开发工具
内核维护者手册 - 配置Git【ChatGPT】
内核维护者手册 - 配置Git【ChatGPT】
|
3月前
|
JavaScript IDE 前端开发
前端开发工具配置 nodejs & git & IDE
前端开发工具配置 nodejs & git & IDE
|
3月前
|
安全 开发工具 git
coding上创建项目、创建代码仓库、将IDEA中的代码提交到coding上的代码仓库、Git的下载、IDEA上配置git
这篇文章是关于如何在IDEA中配置Git、在Coding.net上创建项目和代码仓库,并将IDEA中的代码提交到远程代码仓库的详细教程,涵盖了Git安装、IDEA配置、项目创建、代码提交等步骤。
coding上创建项目、创建代码仓库、将IDEA中的代码提交到coding上的代码仓库、Git的下载、IDEA上配置git
|
3月前
|
开发工具 git
Git使用经验总结2-配置用户名邮箱
Git使用经验总结2-配置用户名邮箱
49 0

相关实验场景

更多