一、在遠程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測試,得到同樣的預期結果