java动态修改nacos的yml配置

本文介绍了两种在Nacos中修改配置文件内容的方法,特别是如何处理accessToken字段的更新。方法一是使用snakeyaml,但会丢失注释;方法二是使用eo-yaml,可以保留注释,但可能会改变格式。每种方法都有其优缺点,实际应用中需评估和测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文只介绍修改方案,没有对方案的可靠性进一步分析。如果涉及的nacos配置项很多,更建议采用数据库表单独存储,并对其进行增删改查。

1、需求

假设nacos上有一个test-dev.yml配置文件,其内容如下:

# 快递相关配置,accessToken每月需要更新一次
express:
  appKey: xxx
  appSecret: xxx
  accessToken: 123456789

现在需要把accessToken字段的值修改成1234

2、实现方式一

第一种方式使用snakeyaml

<dependency>
	<groupId>org.yaml</groupId>
	<artifactId>snakeyaml</artifactId>
	<version>2.0</version>
</dependency>

这种方式有个弊端就是会把配置的注释行给忽略掉

@Value("${spring.profiles.active}")
private String profile;
@Value("${spring.cloud.nacos.config.server-addr}")
private String serverAddr;
private final String group = "DEFAULT_GROUP";

/**
 * 更新Nacos配置
 *
 * @param newAccessToken 
 * @return
 */
private Boolean updateCofig(String newAccessToken) {
   try {
       String dataId = String.format("test-%s.yml", profile);
       Properties properties = new Properties();
       properties.put("serverAddr", serverAddr);
       // 非public时需要设置
       properties.put("namespace", "test");
       // 读取nacos配置
       // 推荐使用NacosConfigManager获取当前ConfigService
       ConfigService configService = NacosFactory.createConfigService(properties);
       String content = configService.getConfig(dataId, group, 5000);
       
       Yaml yaml = new Yaml();
       // 字符串转换成map,这里会把注释行丢弃
       Map<String, Object> data = yaml.load(content);
       // 字段覆盖
       Map<String, Object> express = (Map<String, Object>) data.get("express");
       express.put("accessToken", newAccessToken);
       String yamlStr = yaml.dumpAsMap(data);
       //更新nacos配置
       return configService.publishConfig(dataId, group, yamlStr, ConfigType.YAML.getType());
   } catch (NacosException e) {
       e.printStackTrace();
   }
   return Boolean.FLASE;
}

执行成功后,文件内容被修改成

express:
  appKey: xxx
  appSecret: xxx
  accessToken: 1234
3、实现方式二

如果需要保留注释,则可以用eo-yaml

<dependency>
    <groupId>com.amihaiemil.web</groupId>
    <artifactId>eo-yaml</artifactId>
    <version>7.0.8</version>
</dependency>

详细代码

@Autowired
private NacosConfigManager nacosConfigManager;
@Value("${spring.profiles.active}")
private String profile;
private final String group = "DEFAULT_GROUP";

/**
 * 更新Nacos配置
 *
 * @param newAccessToken
 * @return
 */
private Boolean updateConfig(String newAccessToken) {
    try {
        String dataId = String.format("test-%s.yml", profile);
        //读取nacos配置
        ConfigService configService = nacosConfigManager.getConfigService();
        String content = configService.getConfig(dataId, group, 5000);
        //修改对应的配置
        YamlMapping mapping = Yaml.createYamlInput(content).readYamlMapping();
        // log.info("{}", mapping.toString());
        YamlMapping express = mapping.value("express").asMapping();
        String accessToken = express.string("accessToken");
        // 如果两个token一样则忽略修改
        if(newAccessToken.equals(accessToken)){
            log.warn("token未变化,忽略");
            return true;
        }
        YamlMapping edited = new MergedYamlMapping(
        		// 原有配置
        		mapping,
        		// 需要更新的字段
                () -> Yaml.createYamlMappingBuilder()
                        .add("express", Yaml.createYamlMappingBuilder()
                                .add("accessToken", newAccessToken)
                                .build()
                        ).build(),
                // true-标识覆盖已有值,false则为追加新的字段
                true
        );
        //更新nacos配置
        return configService.publishConfig(dataId, group, edited.toString(), ConfigType.YAML.getType());
    } catch (NacosException | IOException e) {
       e.printStackTrace();
    }
    return Boolean.FALSE;
}

采用这种方式回写后的配置会给字符串加上双引号,并且空行会被移除。如:

# mybatis配置
mybatis:
  # 搜索指定包别名
  typeAliasesPackage: com.text.mapper
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath:mapper/**/*.xml

# 快递相关配置,accessToken每月需要更新一次
express:
  appKey: xxx
  appSecret: xxx
  accessToken: 123456789

以上配置会被修改成

# mybatis配置
mybatis:
  # 搜索指定包别名
  typeAliasesPackage: com.text.mapper
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: "classpath:mapper/**/*.xml"
# 快递相关配置,accessToken每月需要更新一次
express:
  appKey: xxx
  appSecret: xxx
  accessToken: 1234

通常这些操作是不会受影响,但在实际应用中还是要充分的评估和充足的测试,以保证万无一失。

### 如何在 YML 文件中动态配置 Nacos 地址 为了实现 Spring Cloud Alibaba 中 Nacos 的地址动态配置,可以通过 `bootstrap.yml` 或者 `application.yml` 来完成初始配置。以下是具体的实现方式: #### 初始配置 在项目的根目录下创建或编辑 `bootstrap.yml` 文件(推荐优先使用此文件),并添加如下内容以指定 Nacos Server 的地址。 ```yaml spring: application: name: demo-service # 应用名称 cloud: nacos: discovery: server-addr: ${nacos.server.addr:127.0.0.1:8848} # 动态读取环境变量,默认值为本地服务 config: enabled: true # 启用Nacos配置功能 server-addr: ${nacos.server.addr:127.0.0.1:8848} # 配置管理的Nacos服务器地址 ``` 上述代码片段展示了如何通过 `${}` 占位符引入外部环境变量[^1]。如果未提供该环境变量,则会采用默认值 `127.0.0.1:8848`。 #### 环境变量注入 当运行项目时,可以通过命令行或者 Docker 容器等方式传入实际的 Nacos 地址作为环境变量。例如,在 Linux 命令行中执行以下操作即可覆盖默认值: ```bash export nacos.server.addr=your-nacos-server-address:port && java -jar your-application.jar ``` 这样做的好处在于无需修改任何源码或配置文件就能轻松切换不同的开发/测试/生产环境中对应的 Nacos 实例[^3]。 #### 自动刷新机制支持 对于已经部署的应用程序来说,可能还需要考虑在线调整 Nacos 地址的需求场景。此时可以借助于 Spring Boot Actuator 和 Spring Cloud Bus 提供的功能来触发全局范围内的重新加载行为。具体做法是在控制器类上标注 `@RefreshScope` 注解,并配合 `POST /actuator/refresh` 接口调用来即时生效新的配置变更[^2]。 ```java @RestController @RefreshScope public class DynamicConfigController { @Value("${nacos.server.addr}") private String nacosServerAddr; @GetMapping("/getNacosAddress") public String getNacosAddress() { return "Current Nacos Address is:" + nacosServerAddr; } } ``` 以上 Java 类定义了一个简单的 RESTful API `/getNacosAddress` ,它能够返回当前正在使用的 Nacos 地址信息。每当有新版本的配置被推送至 Nacos 并成功同步到各个节点之后,只需访问这个接口便可验证最新状态是否已应用到位。 --- ### 注意事项 尽管上述方法允许一定程度上的灵活性,但在某些极端情况下可能会遇到一些局限性。比如频繁更改注册中心本身的位置可能导致短暂的服务不可达现象;另外需要注意的是,一旦禁用了整个 Nacos Config 组件(`spring.cloud.nacos.config.enabled=false`),那么所有的基于它的特性都将失效。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值