技巧!Spring Boot 動(dòng)態(tài)刷新及實(shí)時(shí)監(jiān)控配置文件的變化
環(huán)境:SpringBoot2.7.18 + SpringCloud2021.0.7
1. 簡(jiǎn)介
在Spring Cloud微服務(wù)架構(gòu)中,配置管理是至關(guān)重要的。隨著業(yè)務(wù)的發(fā)展和服務(wù)的不斷擴(kuò)展,配置信息經(jīng)常需要調(diào)整。如何動(dòng)態(tài)地獲取這些變化,使服務(wù)能夠?qū)崟r(shí)響應(yīng)配置的更新,成為了關(guān)鍵問題。Spring Cloud提供了多種機(jī)制來實(shí)現(xiàn)配置的動(dòng)態(tài)更新,使得開發(fā)人員能夠輕松地管理和應(yīng)用這些變化。
本篇文章不會(huì)結(jié)合Nacos講解,將通過其它的方式手動(dòng)的刷新配置及監(jiān)聽配置文件的變化。
2. 實(shí)戰(zhàn)案例
2.1 依賴管理
<spring-cloud.version>2021.0.7</spring-cloud.version>
<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>項(xiàng)目中主要是需要引入spring-cloud-context包,所以你可以根據(jù)需要隨便引入openfeign或者loadbalancer相應(yīng)的包即可,只要環(huán)境中存在spring-cloud-context包就行了。本示例引入的是:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>該依賴中會(huì)自動(dòng)引入commons和context。
2.2 開啟bootstrap配置
要啟動(dòng)bootstrap配置(也就是默認(rèn)的bootstrap.yml配置生效)有以下2中方式:
第一種:
引入下面依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>第二種:
啟動(dòng)應(yīng)用程序時(shí)添加如下參數(shù)
-Dspring.cloud.bootstrap.enabled=truebootstrap.yml配置文件生效關(guān)鍵是BootstrapApplicationListener監(jiān)聽器。
部分代碼
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
if (!bootstrapEnabled(environment) && !useLegacyProcessing(environment)) {
return;
}
// ...
}推薦第一種方式。
2.3 初始配置
bootstrap.yml配置內(nèi)容如下
pack:
name: ooxx對(duì)應(yīng)的屬性配置類
@Component("pp")
@ConfigurationProperties(prefix = "pack")
public class PackProperties {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}測(cè)試接口
@RestController
@RequestMapping("/pack")
public class PackController {
@Resource(name = "pp")
private PackProperties props ;
@GetMapping("")
public PackProperties p() {
return props ;
}
}
圖片
正確顯示配置信息。
如果你修改配置文件pack.name默認(rèn)情況下是不會(huì)有任何變化的。要正確的使得配置文件實(shí)時(shí)更新,我們可以手動(dòng)的觸發(fā)配置刷新動(dòng)作。
觸發(fā)刷新動(dòng)作
@Resource
private ContextRefresher contextRefresher ;
@GetMapping("/refresh")
public Object refresh() {
return this.contextRefresher.refresh() ;
}通過ContextRefresher#refresh方法會(huì)觸發(fā)2個(gè)核心動(dòng)作:
- 重新初始化refresh作用域的bean對(duì)象
- @ConfigurationProperties注解的類(或方法@Bean)會(huì)重新初始化觸發(fā)EnvironmentChangeEvent事件。
修改配置文件內(nèi)容如下:
pack:
name: ooxx調(diào)用上面/refresh接口后,無需重啟服務(wù),配置信息已經(jīng)動(dòng)態(tài)刷新
圖片
上面的示例是需要對(duì)@ConfigurationProperties進(jìn)行重寫綁定,所以我們可以通過監(jiān)聽EnvironmentChangeEvent事件在程序中監(jiān)聽配置的變化。
@Component
public class PackApplicationEventListener implements ApplicationListener<EnvironmentChangeEvent> {
@Resource
private Environment env ;
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
System.out.println(event.getKeys()) ;
System.out.println(env.getProperty("pack.name")) ;
}
}當(dāng)配置發(fā)生變化后,上面的監(jiān)聽程序?qū)⒈挥|發(fā)。
控制臺(tái)輸出
[pack.name]
xxxooo



























