SpringCloud统一配置Config

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

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

码云仓库概况
15200008-485337a56586a62c.png
分支

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

token=false

如下图所示:


15200008-440246a7665f4d15.png
dev分支配置

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

token=true

如下图所示:


15200008-22fa0ed1cd2d95a5.png
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的一些基本配置:


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


    15200008-3596072b7c4230f4.png
    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


    15200008-0edaf516d400d4c0.png
    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文件,


15200008-3d60e3531253d61e.png
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;
    }
}

启动项目,测试:


15200008-08a38bb3a3fdabe7.png
postman

15200008-5b3ec1000faa5251.png
控制台

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

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

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

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


15200008-22898c478d895bff.png
在配置文件中关闭安全机制

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

------------false---------------

然后将码云上的配置文件修改:token=true
15200008-800ca2cfca5ce291.png
token=true

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


15200008-cbc81f9500215515.png
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文件:

15200008-f094c482f851ecb0.png
jar文件

将这两个jar文件复制到java源文件里面,如图:
15200008-26690d97fbc0ff7f.png
复制文件

,如果是jre则直接放到jre\lib\security目录下。

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

2.重启config-server项目

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

15200008-237ba6554baaea1b.png
image.png

可以看到没有key,因此我们需要在项目中设置一个加密的秘钥(还需要创建bootstrap配置文件):
15200008-1b415e2b2f215274.png
配置key

(2)再次查看状态、加密、解密
15200008-71616f7a6be440ce.png
准备就绪

可以看到已经准备就绪了,然后就可以进行加密解密的操作了。
15200008-4f01305c5230f05e.png
加密

需要将请求方式改为post,然后在body中输入要加密的字符串,可以看到返回了一个很长的字符串,这个就是加密后的字符串。
然后来看一下解密:将以上得到的字符串输入到body中:
15200008-bf6d17355701679f.png
解密

(3)修改远程配置文件
将远程的配置文件修改成加密后的密文:
15200008-20d443bb0313c3b8.png
修改配置文件

可以看到我在配置文件之前加了(cipher),这个就是一个标识,告诉远程读取配置文件那个服务这个是被加密的,需要解密。

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

(4)测试

15200008-72caf9c3cc18e29c.png
测试结果1

15200008-94672aaf1ac9282f.png
测试结果2

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值