SpringCloud統一配置Config

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章