就是项目运行时动态修改yam文件并加载,具体原理不懂,百度拼来的,只给实现方法
首先是依赖以及版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
yml配置文件
management:
health:
redis:
enabled: false #关闭对redis的自动检查,这个可以忽略
endpoints:
web:
exposure:
include: refresh #开放修改端口(网上说的我也不知道啥意思)
elasticsearch:
password: 123456 #用来测试的数据
配置类
配合配置文件达到动态修改的目的
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author tj
* @apiNote
* @date 2021/8/30
*/
@Data
@Component
@ConfigurationProperties(prefix="elasticsearch")
public class ESConfig {
private String host;
private int port;
private String user;
private String password;
// ... 省略getter() setter()
}
测试类:通过页面修改配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.yaml.snakeyaml.Yaml;
import java.io.FileInputStream;
import java.io.*;
import java.io.IOException;
import java.util.Map;
/**
* @author tj
* @apiNote
* @date 2021/8/30
*/
@RestController
public class EsUserController {
@Qualifier("legacyContextRefresher")
@Autowired
private ContextRefresher contextRefresher;
@Autowired
private ESConfig esConfig;
@GetMapping("/api/refresh/{value}")
public void refresh(@PathVariable String value) throws IOException {
// 修改配置文件
updateYamlFile(value);
// 刷新配置文件
//contextRefresher.refresh();
// 使用刷新后的配置
System.out.print(esConfig.getPassword());
}
public void updateYamlFile(String value) throws IOException {
String src = EsUserController.class.getClassLoader().getResource("application.yml").getPath();
//String src = "src/main/resources/application.yml";
Yaml yaml = new Yaml();
FileWriter fileWriter;
FileInputStream fileInputStream = new FileInputStream(new File(src));
Map<String, Object> yamlMap = yaml.load(fileInputStream);
Map<String, Object> esMap = (Map<String, Object>) yamlMap.get("elasticsearch");
esMap.put("password", value);
//字符输出
fileWriter = new FileWriter(new File(src));
//用yaml方法把map结构格式化为yaml文件结构
fileWriter.write(yaml.dumpAsMap(yamlMap));
//刷新
fileWriter.flush();
//关闭流
fileWriter.close();
fileInputStream.close();
new Thread(() ->contextRefresher.refresh()).start();
}
}
另一个测试类,来验证结果
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author tj
* @apiNote
* @date 2021/8/30
*/
@RestController
public class TestB {
@Value("${elasticsearch.password}")
private String password;
@RequestMapping("/test2")
public String test2 (){
return this.password;
}
}
启动项目,通过页面访问 http://localhost:8080/test2
可以看到返回了我们配置文件中的值
image.png
elasticsearch:
password: 123456 #用来测试的数据
此时访问 http://localhost:8080/api/refresh/9992323
然后再次访问 http://localhost:8080/test2
image.png
可以发现 这个password的值已经变成了我们想要的值
查看项目中的文件
image.png
image.png
成功的修改了部署文件中的值,证明这个方法是可行的
缺点:
修改完成之后加载配置文件相当于项目重新启动了一次,中间会出现短暂服务不能访问的情况,慎用!
建议配合redis或者数据库等中间件使用,无需加载。