项目中用到nacos管理配置,每次对配置进行修改后,必须重启服务才能生效,如果是生产环境则影响很大,所以想要将某些变动性比较大的配置,比如一些服务的地址、密码等,可能经常会更换,这时候想要将这部分配置能够在系统web界面上随时查看和随时进行修改,还想要即时生效不需要重启服务,下列就是该功能实现代码,实现对对象存储服务和文件存储服务相关配置进行查看和更新:
1、添加nacos配置中心的依赖
<!--注册中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--配置中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、 在DEFAULT_GROUP组下添加application.yml公共配置文件,S3服务配置在这里面;添加mcp-api-master.yml子项目配置文件,nfs服务配置信息在这里
3、bootstrap.yml添加共享配置信息
spring:
application:
name: virt-biz
quartz:
job-store-type: jdbc
cloud:
nacos:
config:
server-addr: ${NACOS_HOST:192.168.114.160}:${NACOS_PORT:8848}
file-extension: yml
shared-configs:
- dataId: application.yml
refresh: true
- dataId: CloudInitDisk.yml
refresh: true
- dataId: mcp-api-master.yml
refresh: true
namespace: ${NAMESPACE:}
username: nacos
password: ${NACOS_PWD:******}
discovery:
namespace: ${NAMESPACE:}
4、写前端页面
点击对象存储配置按钮,弹出以下弹框,显示当前nacos中S3的三个配置项。
例如修改配置项服务地址端口号8080为8081,修改后点击确定,去nacos客户端查看,端口号已经被修改为了8081,修改成功。
再次点击按钮,可以看到获取的当前配置已经更新为了8081
5、后端接口
需要4个接口,分别是获取配置和更新配置接口:
@GetMapping("/getObjectStorageConfig")
@ApiOperation(value = "获取对象存储服务配置")
public R<Map<String,String>> getObjectStorageConfig() {
return R.ok(this.storageService.getObjectStorageConfig());
}
@GetMapping("/getFileStorageConfig")
@ApiOperation(value = "获取文件存储服务配置")
public R<Map<String,Object>> getFileStorageConfig() {
return R.ok(this.storageService.getFileStorageConfig());
}
@PutMapping("/editObjectStorageConfig")
@ApiOperation(value = "修改对象存储服务配置")
public R<String> editObjectStorageConfig(@RequestBody Map<String,String> map) {
boolean flag = this.storageService.editObjectStorageConfig(map);
return flag ? R.ok(null,"修改配置文件成功") : R.failed("需改配置文件失败");
}
@PutMapping("/editFileStorageConfig")
@ApiOperation(value = "修改对象存储服务配置")
public R<String> editFileStorageConfig(@RequestBody Map<String,Object> map) {
boolean flag = this.storageService.editFileStorageConfig(map);
return flag ? R.ok(null,"修改配置文件成功") : R.failed("需改配置文件失败");
}
具体实现代码:
@Override
public Boolean editObjectStorageConfig(Map<String, String> map){
try{
String dataId = "application.yml";
String group = "DEFAULT_GROUP";
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR,serverAddr);
properties.put(PropertyKeyConst.USERNAME, username);
properties.put(PropertyKeyConst.PASSWORD, password);
ConfigService configService = NacosFactory.createConfigService(properties);
//监听配置
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("recieve:" + configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
if(configService != null) {
//获取配置文件内容
String config = configService.getConfig(dataId, group, 5000);
System.out.println(config);
// 遍历替换规则映射,将新值替换到配置字符串中
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
String placeholder = key + ":" + value;
if (!config.contains(placeholder)) {
switch (key) {
case "S3_USER" :
config = config.replace(access_key, value);
continue;
case "S3_PWD" :
config = config.replace(secret_key, value);
continue;
case "S3_ENDPOINT":
config = config.replace(endpoint, value);
}
}
}
return configService.publishConfig(dataId, group, config);
}
} catch (NacosException e) {
System.err.println("Nacos配置更新异常:" + e.getMessage());
}
return false;
}
主要通过下面的方法创建一个configService,利用NacosFactory中的createConfigService方法:
ConfigService configService = NacosFactory.createConfigService(properties);
再通过configService的getConfig方法获取到nacos客户端上的对应配置文件内容:
String config = configService.getConfig(dataId, group, 5000);
将内容更新后,再通过configService的publishConfig发布配置文件的新版本:
boolean flag = configService.publishConfig(dataId, group, config);
发布成功后,在系统web页面再次点击按钮获取配置时发现获取到的配置文件内容仍然是未更新的,这是因为服务重启才能获取到最新的配置,重启服务,再次查看,这时配置显示已更新。
实现nacos配置热更新:在@Value注入的变量所在类上添加注解@RefreshScope
这时就实现了修改配置的实时更新。