美文网首页
SpringCloud统一配置Config

SpringCloud统一配置Config

作者: 一直想上树的猪 | 来源:发表于2019-08-04 00:53 被阅读0次

    一、在远程Git仓库创建配置信息

    因为在国内访问github是很不稳定的,所以我选择码云来创建git仓库去保存我的项目配置信息

    码云仓库概况
    分支

    首先创建成功之后有两个分支:dev和master,然后分别在两个分支中创建一个文件夹config-file,在config-file文件夹下新建文件:(dev分支创建dm-gateway-zuul-dev.properties),里面只有一个配置信息:

    token=false
    

    如下图所示:


    dev分支配置

    然后同样的,在master分支,新建文件夹config-file,但是新建文件的时候文件名要写:dm-gateway-zuul-master.properties,同样只有一个配置信息:

    token=true
    

    如下图所示:


    master分支配置

    二、创建config server加载远程配置

    1.创建spring项dm-config-server,pom文件:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.springcloud</groupId>
        <artifactId>dm-config-server</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>dm-config-server</name>
        <description>Demo project for Spring Cloud</description>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <spring-cloud.version>Dalston.SR4</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    其中比较重要的就是加入了spring-cloud-config-server这一组件,然后在启动类中加入注解:@EnableDiscoveryClient证明是一个可以被发现的服务,然后加入@EnableConfigServer声明这个项目是一个cloud的核心配置中心config。

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableConfigServer
    public class DmConfigServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DmConfigServerApplication.class, args);
        }
    
    }
    

    之后就是配置文件了,分析:我们需要让这个项目去访问我在第一步中新建的那个项目,就需要对其进行相应的配置,然后加上cloud的一些基本配置:


    application.yml
    2.启动项目,测试
    • 1.我首先访问localhost:7900/dm-gateway-zuul/master/master


      localhost:7900/dm-gateway-zuul/master/master

    为什么要请求这个路径?
    之前在码云上创建文件的时候,master分支的文件名是:dm-gateway-zuul-master.properties,这个文件名的定义其实是有规范的:名字/版本/分支,即这个文件名被拆成了两部分:一个是dm-gateway-zuul声明它是关于zuul的配置文件,而后面的master是说这是一个master版本。而在路径上的最后面的那个master其实是分支的意思。

    • 2.访问localhost:7900/dm-gateway-zuul/dev/dev


      localhost:7900/dm-gateway-zuul/dev/dev

    三、谁需要这个配置信息,谁就去调用这个server

    根据我创建的这个文件,就能知道,这个其实就是为了网关zuul去创建的配置文件。如果想要获取远程的配置,需要在dm-gateway-zuul项目再引入一个依赖

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

    接下来有一件事情需要注意:我肯定需要去读远程的那个配置信息,但是它很特殊,不能去将git仓库相关信息放到application.yml文件中去,我肯定是要比这个配置文件早加载配置文件的,优先级很高。怎么说呢?就是application.yml是负责为整个项目运行去加载配置文件的,在这边有一个配置文件:bootstrap.yml文件,


    bootstrap.yml

    这个文件就是负责为整个项目加载配置文件,而不管项目是否运行。所以说在spring里面其实还有一个优先级更高的配置文件。

    spring:
      application:
        name: dm-gateway-zuul
      cloud:
        config:
          uri: http://localhost:7900
          profile: dev
          label: dev
    # config server地址
    # application name + profile版本(dev、 pro、test)
    # 分支
    

    即声明注册的名称、找到加载远程配置信息的server,提供足够的参数,这些参数就是application name + profile版本(dev、 pro、test),还有分支。
    紧接着在zuul的过滤器中去进入加载完的配置信息,进行一个注入,跟普通的配置文件注入没什么区别:

       @Value("${token}")
        private boolean token;
    

    四、修改filter逻辑

    在preFilter中:

    @Component
    //重新注入
    @RefreshScope
    public class PreFilter extends ZuulFilter {
    
        @Value("${token}")
        private boolean token;
    
        @Override
        public String filterType() {
            //过滤器类型
            return FilterConstants.PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            //同类型的过滤器,数字越小,优先级越高
            return 1;
        }
    
        @Override
        public boolean shouldFilter() {
            //希望这个过滤器发挥作用就设置为true,不希望发挥作用就设置为false
            return true;
        }
    
        @Override
        public Object run() {
            RequestContext context = RequestContext.getCurrentContext();
            HttpServletRequest request = context.getRequest();
            System.out.println("------------"+token+"---------------");
            if (token){
                String token = request.getHeader("authorization");
                if (token != null ){
                    //登录过
                    return "过!";
                }else{
                    //无效
                    //告诉后面的过滤器,在当前就已经出问题了,没必要去进行路由转发了
                    context.setSendZuulResponse(false);
                    context.setResponseStatusCode(401);
                    context.setResponseBody("{\"msg\":\"401,access without permission,please login first.\"}");
                    return "access denied";
                }
            }
            return "token 为false";
        /*    String key = request.getParameter("key");
            System.out.println(key+"access filter 1");
            context.set("thirdfilter",true);
            if ("1".equals(key)){
                context.setSendZuulResponse(false);
            }else if ("".equals(key)){
                context.set("thirdfilter",false);
            }*/
    //        return null;
        }
    }
    

    启动项目,测试:


    postman
    控制台

    没问题,然后我修改远程仓库的配置文件,将false改为true,再次访问,结果发现没有变,需要重新启动服务才能生效,是因为加载配置文件不是动态的,因为是单例的只能加载一次,加载完了就在系统中运行了,不会因为远程仓库信息变了而去通知我们的程序去加载,这样的话每次就得手动重启项目才能使配置文件生效,明显是不可以的,因而我们引入了SpinrgCloud的另一个组件---BUS,但是在这里我们也可以配置一个依赖不用去手动重启项目,只需要刷新配置即可。

    五、在远程配置信息变更后实现刷新

    1.添加依赖
    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    添加actuator之后,就可以实现刷新机制,但是我们需要通知actuator谁需要刷新,因此在preFilter上加入注解@RefreshScope。(Spring是单例加载,注入是刚开始启动项目的时候一锤子买卖,但是运行过程中要想重新注入就需要这个注解),同时在配置文件中关闭安全机制


    在配置文件中关闭安全机制

    重启项目,首先远程的dev配置是token=false,测试:localhost:7600/user/userlogin
    控制台中显示

    ------------false---------------
    
    然后将码云上的配置文件修改:token=true token=true

    然后将项目刷新:localhost:7600/refresh


    token刷新
    可以看到在返回结果里告知了我们token这个配置变了。

    刷新的逻辑:
    git修改了,config-server不知道git被修改了,那么zuul更不可能知道,当我们发起刷新的请求的时候,逼着config-server去远程读取一次git的配置文件,然后将新的配置信息返回给zuul

    然后再次测试:localhost:7600/user/userlogin
    控制台中显示

    ------------true---------------
    

    问题:每次刷新都需要手动刷新,很不方便,后期如果要实现动态刷新还是需要BUS组件

    六、配置信息加密

    1.JCE

    JCE默认是集成在JDK开发环境中的,不过我还需要对它进行调整,Oracle公司对java组件发布的时候对加密算法的强度是有限制的,即默认的JCE里面是不支持高强度加密的,但是我们可以去Oracle官网去获得高强度的加密方式。首先访问Oracle官网:JCE for java8
    下载成功之后里面有两个jar文件:

    jar文件
    将这两个jar文件复制到java源文件里面,如图:
    复制文件
    ,如果是jre则直接放到jre\lib\security目录下。

    注意:如果在开发机修改完之后,将来部署上线的时候服务器上也要做这个事情,打破JCE的限制

    2.重启config-server项目

    然后我们可以查看到一些加密解密的一些url
    (1)查看状态

    image.png
    可以看到没有key,因此我们需要在项目中设置一个加密的秘钥(还需要创建bootstrap配置文件):
    配置key
    (2)再次查看状态、加密、解密
    准备就绪
    可以看到已经准备就绪了,然后就可以进行加密解密的操作了。
    加密
    需要将请求方式改为post,然后在body中输入要加密的字符串,可以看到返回了一个很长的字符串,这个就是加密后的字符串。
    然后来看一下解密:将以上得到的字符串输入到body中:
    解密
    (3)修改远程配置文件
    将远程的配置文件修改成加密后的密文:
    修改配置文件
    可以看到我在配置文件之前加了(cipher),这个就是一个标识,告诉远程读取配置文件那个服务这个是被加密的,需要解密。

    如果是用的properties文件,信息两端不要加引号,如果是yml格式的文件,参数值两边要加单引号:token='(cipher)密文'

    (4)测试

    测试结果1
    测试结果2
    同理,将true改为false测试,得到同样的预期结果

    相关文章

      网友评论

          本文标题:SpringCloud统一配置Config

          本文链接:https://www.haomeiwen.com/subject/sgwqdctx.html