Spring Cloud Config爲分佈式系統中的外部化配置提供了服務器端和客戶端支持。有了配置服務器,您就有了一箇中心位置來管理跨全部環境的應用程序的外部屬性。本文記錄實現一個配置中心、客戶端獲取配置參數、refresh手動刷新html
官方文檔:https://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.htmlgit
幫助文檔:https://spring.io/guides/gs/centralized-configuration/github
首先咱們基於以前的代碼,在springCloud工程下面新建一個Config Server,是一個springboot項目,而且在Eureka上面註冊服務(還不會服務註冊與發現的,請戳:SpringCloud系列——Eureka 服務註冊與發現),本例使用的是GitHubweb
maven引jarajax
<!-- config-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
登陸GitHub,新建一個public倉庫:config-server,而且添加測試項目對應的配置文件:myspringboot-dev.properties,並設置幾個值spring
配置文件json
server.port=1112 spring.application.name=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ #健康檢查(須要spring-boot-starter-actuator依賴) eureka.client.healthcheck.enabled=true # 續約更新時間間隔(默認30秒) eureka.instance.lease-renewal-interval-in-seconds=10 # 續約到期時間(默認90秒) eureka.instance.lease-expiration-duration-in-seconds=10 #鏈接GitHub spring.cloud.config.server.git.uri=https://github.com/huanzi-qch/config-server.git spring.cloud.config.server.git.search-paths=config-server spring.cloud.config.label=master spring.cloud.config.server.git.username=****** spring.cloud.config.server.git.password=******
啓動類加入註解@EnableConfigServerbootstrap
@EnableConfigServer @EnableEurekaClient @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
啓動項目,訪問http://localhost:1112/myspringboot-dev.properties/,發現有中文亂碼緩存
注:倉庫中的配置文件會被轉換成web接口,訪問規則:tomcat
解決中文亂碼,參考:https://blog.csdn.net/sinat_38843093/article/details/79960777
新建自定義解析器MyPropertiesHandler,繼承PropertiesPropertySourceLoader,重寫方法
/** * 解決中文亂碼問題 * 參考:https://blog.csdn.net/sinat_38843093/article/details/79960777 */ public class MyPropertiesHandler extends PropertiesPropertySourceLoader { @Override public String[] getFileExtensions() { return new String[]{"properties", "xml"}; } @Override public List<PropertySource<?>> load(String name, Resource resource) throws IOException { ArrayList<PropertySource<?>> list = new ArrayList<>(); Properties properties = getProperties(resource); if (!properties.isEmpty()) { list.add(new PropertiesPropertySource(name, properties)); } return list; } private Properties getProperties(Resource resource) throws IOException { Properties properties = new Properties(); InputStream inputStream = resource.getInputStream(); properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); inputStream.close(); return properties; } }
resources文件夾下面新建META-INF文件夾,在裏面建立spring.factories文件,指定使用咱們自定義的解析器
org.springframework.boot.env.PropertySourceLoader=cn.huanzi.qch.config.configserver.MyPropertiesHandler
從新啓動項目,在自定義解析器後進行斷點調試,發現解析的時候中文亂碼問題得以解決,但響應回去仍是亂碼
解決http響應中文亂碼問題
配置文件添加
#解決http響應數據中文亂碼問題 spring.http.encoding.force=true spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true server.tomcat.uri-encoding=UTF-8
最終效果
咱們去GitHub修改配置中心的值,看下config server能不能實時獲取最新數據
改完後刷新http://localhost:1112/myspringboot-dev.properties/,配置中心能夠實時獲取最新數據
客戶端咱們直接用以前的項目:myspringboot,這裏就當作一個在Eureka上註冊了的普通springboot項目
maven引入jar
<!-- config-client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
application.properties
#設置服務端口 server.port=10087 spring.application.name=myspringboot #eureka eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ #健康檢查(須要spring-boot-starter-actuator依賴) eureka.client.healthcheck.enabled=true # 續約更新時間間隔(默認30秒) eureka.instance.lease-renewal-interval-in-seconds=10 # 續約到期時間(默認90秒) eureka.instance.lease-expiration-duration-in-seconds=10 #超時時間 feign.httpclient.connection-timeout=30000
使用優先級更高的bootstrap.properties進行config的配置,由於
#關閉spring cloud config,spring cloud默認要從config中讀取配置,經過該配置,只從本地application.properties中讀取配置 #spring.cloud.config.enabled=false #配置文件名(當應用名跟配置文件相同時能夠不用配置) spring.cloud.config.name=myspringboot # dev 開發環境配置文件 | test 測試環境 | pro 正式環境 spring.cloud.config.profile=dev # 遠程倉庫的分支 spring.cloud.config.label=master #指定配置中心名稱(若是使用eureka能夠這樣配置) #spring.cloud.config.discovery.service-id=config-server #啓用發現服務功能 #spring.cloud.config.discovery.enabled=true #配置服務中心地址(若是不使用eureka能夠直接配置url路徑) spring.cloud.config.uri=http://localhost:1112/
若是使用從eureka獲取配置中心實例,則要在指定服務以前進行註冊配置,不然會報錯,由於你還沒在Eureka註冊就去Eureka查找配置中心,如:
#設置服務端口 server.port=10087 spring.application.name=myspringboot #eureka eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ #健康檢查(須要spring-boot-starter-actuator依賴) eureka.client.healthcheck.enabled=true # 續約更新時間間隔(默認30秒) eureka.instance.lease-renewal-interval-in-seconds=10 # 續約到期時間(默認90秒) eureka.instance.lease-expiration-duration-in-seconds=10 #超時時間 feign.httpclient.connection-timeout=30000 #關閉spring cloud config,spring cloud默認要從config中讀取配置,經過該配置,只從本地application.properties中讀取配置 #spring.cloud.config.enabled=false #配置文件名(當應用名跟配置文件相同時能夠不用配置) spring.cloud.config.name=myspringboot # dev 開發環境配置文件 | test 測試環境 | pro 正式環境 spring.cloud.config.profile=dev # 遠程倉庫的分支 spring.cloud.config.label=master #指定配置中心名稱(若是使用eureka能夠這樣配置) spring.cloud.config.discovery.service-id=config-server #啓用發現服務功能 spring.cloud.config.discovery.enabled=true #配置服務中心地址(若是不使用eureka能夠直接配置url路徑) #spring.cloud.config.uri=http://localhost:1112/
測試
咱們直接在啓動類進行測試
@EnableEurekaClient @SpringBootApplication @RestController public class MyspringbootApplication{ public static void main(String[] args) { SpringApplication.run(MyspringbootApplication.class, args); } @Value("${huanzi.qch.config.server.username}") private String username; /** * 訪問首頁 */ @GetMapping("/index") public String index(){ return "hello springboot!username:" + username; } }
查看啓動日誌,客戶端已經發現了配置中心,而且從配置中心發現了myspringboot配置文件
訪問http://localhost:10087/index,值已經取到了
其實客戶端(Config Client)也是能夠讀取服務端(Config Server)配置文件裏面的值,例如:
客戶端(Config Client)是能夠讀取到這個值的,因而可知,是客戶端是讀取了服務端的數據,而服務端負責實時獲取GitHub上面的數據
咱們已經在客戶端取到了配置中心的值,但當咱們修改GitHub上面的值時,服務端(Config Server)能實時獲取最新的值,但客戶端(Config Client)讀的是緩存,沒法實時獲取最新值
spring已經爲咱們解決了這個問題,那就是客戶端使用post去觸發refresh,獲取最新數據,須要依賴spring-boot-starter-actuator
<!-- actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
對應的controller類加上@RefreshScope
@RefreshScope @EnableEurekaClient @SpringBootApplication @RestController public class MyspringbootApplication{ public static void main(String[] args) { SpringApplication.run(MyspringbootApplication.class, args); } @Value("${huanzi.qch.config.server.username}") private String username; /** * 訪問首頁 */ @GetMapping("/index") public String index(){ return "hello springboot!username:" + username; } }
啓動後查看日誌發現,actuator有個基礎路徑/actuator,同時還暴露了兩個終端(不知道是哪兩個端點...)
可是當咱們post訪問http://localhost:10087/actuator/refresh時,報404,這是什麼回事?
注:這裏插一句話:從網上找了個js的ajax(要注意content-type的類型)
var Ajax={ get: function(url, fn) { // XMLHttpRequest對象用於在後臺與服務器交換數據 var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = function() { // readyState == 4說明請求已完成 if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) { // 從服務器得到數據 fn.call(this, xhr.responseText); } }; xhr.send(); }, // datat應爲'a=a1&b=b1'這種字符串格式,在jq裏若是data爲對象會自動將對象轉成這種字符串格式 post: function (url, data, fn) { var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); // 添加http頭,發送信息至服務器時內容編碼類型 xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) { fn.call(this, xhr.responseText); } }; xhr.send(data); } }
Ajax.post("http://localhost:10087/actuator/refresh",null,function(data){console.log(data)})
通過層層查找,最後在幫助文檔發現:默認狀況下,自Spring Boot 2.0以來,默認狀況下不會公開Actuator端點,須要手動暴露端點
配置文件暴露端點
#只暴露refresh,固然也能夠暴露全部:=* management.endpoints.web.exposure.include=refresh
重啓客戶端,咱們將GitHub配置文件改回:huanzi.qch.config.server.username: 張三
訪問測試接口,仍是張三1
post調用refresh
刷新,數據更新
這裏總結一下遇到的坑:
調用refresh報404的時候,百度查找都是說默認安全攔截,配置關閉:management.security.enabled=false,配置上去的時候發現報錯,波浪線,被棄用了,
最後仍是靠Google,在知乎(https://zhuanlan.zhihu.com/p/34784934)上面找到了答案
而且吐槽吐槽百度:
一樣的關鍵字,Google搜出來的第一個就能解決問題
而垃圾百度,沒一個能夠...
代碼已經開源、託管到個人GitHub、碼雲: