一、在远程Git仓库创建配置信息
因为在国内访问github是很不稳定的,所以我选择码云来创建git仓库去保存我的项目配置信息
码云仓库概况
首先创建成功之后有两个分支:dev和master,然后分别在两个分支中创建一个文件夹config-file,在config-file文件夹下新建文件:(dev分支创建dm-gateway-zuul-dev.properties),里面只有一个配置信息:
token=false
如下图所示:
然后同样的,在master分支,新建文件夹config-file,但是新建文件的时候文件名要写:dm-gateway-zuul-master.properties,同样只有一个配置信息:
token=true
如下图所示:
二、创建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的一些基本配置:
2.启动项目,测试
-
1.我首先访问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
三、谁需要这个配置信息,谁就去调用这个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文件,
这个文件就是负责为整个项目加载配置文件,而不管项目是否运行。所以说在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;
}
}
启动项目,测试:
没问题,然后我修改远程仓库的配置文件,将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
然后将项目刷新:localhost:7600/refresh
可以看到在返回结果里告知了我们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文件复制到java源文件里面,如图:
,如果是jre则直接放到jre\lib\security目录下。
注意:如果在开发机修改完之后,将来部署上线的时候服务器上也要做这个事情,打破JCE的限制
2.重启config-server项目
然后我们可以查看到一些加密解密的一些url
(1)查看状态
可以看到没有key,因此我们需要在项目中设置一个加密的秘钥(还需要创建bootstrap配置文件):
(2)再次查看状态、加密、解密
可以看到已经准备就绪了,然后就可以进行加密解密的操作了。
需要将请求方式改为post,然后在body中输入要加密的字符串,可以看到返回了一个很长的字符串,这个就是加密后的字符串。
然后来看一下解密:将以上得到的字符串输入到body中:
(3)修改远程配置文件
将远程的配置文件修改成加密后的密文:
可以看到我在配置文件之前加了(cipher),这个就是一个标识,告诉远程读取配置文件那个服务这个是被加密的,需要解密。
如果是用的properties文件,信息两端不要加引号,如果是yml格式的文件,参数值两边要加单引号:token='(cipher)密文'
(4)测试
同理,将true改为false测试,得到同样的预期结果