初学者不知道有没有这个疑惑:我明明已经在 SpringBoot 应用的 bootstrap.yml 配置文件中,通过
spring.cloud.nacos.config.refresh-enabled=true
开启配置文件动态刷新了,为什么在 Controller 控制类中使用 @Value 注解无法获取到配置文件修改后的值 ? ? ?
这是因为你理解错了:动态刷新配置文件 和 动态获取配置文件的值
-
动态刷新配置文件:在 SpringBoot 应用的 bootstrap.yml 配置文件中,可以通过
spring.cloud.nacos.config.refresh-enabled=true
开启配置文件动态刷新。也就是配置文件发生修改后,会自动刷新配置文件,使修改后的配置文件生效,否则你获取的还是原本的哪个旧的配置文件。 -
动态获取配置文件的值:是指在配置文件发生修改,并经过
spring.cloud.nacos.config.refresh-enabled=true
刷新生效后。通过 @Value 可以获取到配置文件更新后的值。这需要使用 @RefreshScope 注解来实现。
动态刷新配置文件
1. 在 SpringBoot 应用的 bootstrap.yml 配置文件中,对配置中心中 data-id 为 config-caidong-redis.properties 的配置文件开启动态刷新。
spring:
cloud:
nacos:
config:
#配置中心
server-addr: 192.168.184.129:8849
#需要配置nacos的 用户名和密码,否则报unknown user!错误
username: nacos
password: nacos
#对于非public命名空间的配置文件,需要指定命名空间ID
namespace: 29f2547c-ce20-40b4-b76c-e4ae53f481fe
extension-configs:
- data-id: config-caidong-redis.properties #配置data-id
group: dev #分组名称
refresh: true #开启动态刷新,默认为false
2. 启动 Spring Boot 应用测试的代码如下:
@SpringBootApplication
public class Nacos8030Apllication {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Nacos8030Apllication.class, args);
while(true) {
//当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置
String redisName = applicationContext.getEnvironment().getProperty("com.redis.name");
System.out.println("redisName: " + redisName);
TimeUnit.SECONDS.sleep(1);
}
}
3. 如下所示,当变更 com.redis.name 时,应用程序中能够获取到最新的值:
redisName: 缓存配置
redisName: 缓存配置
redisName: 缓存配置
2022-12-11 20:24:46.918 INFO 1636 --- [ restartedMain] com.cd.nacos.Nacos8030Apllication : Started Nacos8030Apllication in 6.054 seconds (JVM running for 75.326)
2022-12-11 20:24:46.920 INFO 1636 --- [ restartedMain] c.a.c.n.refresh.NacosContextRefresher : listening config: dataId=config-caidong-redis02.properties, group=dev
//从 Enviroment 中 读取到更改后的值
redisName: 缓存配置--update
redisName: 缓存配置--update
将 refresh 属性注释 或者 设置成false,关闭配置自动刷新。也就是配置文件内容发生变更后,从 Enviroment 中 读取到的还是未更改前的值。
动态获取配置文件的值
配置通常用在 Bean 里面,在 Bean 中通过@Value 注解来获取配置信息,但 @Value 可以获取到配置中心的值,却无法动态感知获取修改后的配置内容。想要 @Value 可以动态获取配置修改后的值,需要在 Bean 上添加 @RefreshScope 注解。
使用 @RefreshScope 注解的前提是,变更后的配置文件进行了动态刷新 (
spring.cloud.nacos.config.refresh-enabled=true
开启了动态刷新)。否则配置文件都没有刷新,那肯定就不可能获取到变更后的配置内容。
1. 在 SpringBoot 应用的 bootstrap.yml 配置文件中,对配置中心中 data-id 为 config-caidong-redis.properties 的配置文件开启动态刷新。
spring:
cloud:
nacos:
config:
#配置中心
server-addr: 192.168.184.129:8849
#需要配置nacos的 用户名和密码,否则报unknown user!错误
username: nacos
password: nacos
#对于非public命名空间的配置文件,需要指定命名空间ID
namespace: 29f2547c-ce20-40b4-b76c-e4ae53f481fe
extension-configs:
- data-id: config-caidong-redis.properties #配置data-id
group: dev #分组名称
refresh: true #开启动态刷新,默认为false
2. 在 SpringBoot 应用中的 ConfigController 控制类中,使用 @Value 注解获取配置中心的配置内容。
@RestController
@RequestMapping("/config")
//@RefreshScope /*动态获取最新配置内容*/
public class ConfigController {
@Value("${com.mysql.name}")
private String mysqlName;
@Value("${com.redis.name}")
private String redisName;
@Value("${com.rocketmq.name}")
private String rocketmqName;
@GetMapping("/common")
public String show(){
return "mysqlName: " + mysqlName + ", redisName: " + redisName + ", rocketmqName: " + rocketmqName;
}
}
3. 如下所示,当变更 com.redis.name 时,应用程序中无法获取到修改后的最新内容:
4. 在 Bean 上添加 @RefreshScope 注解。
@RestController
@RequestMapping("/config")
@RefreshScope /*动态获取最新配置内容*/
public class ConfigController {
@Value("${com.mysql.name}")
private String mysqlName;
@Value("${com.redis.name}")
private String redisName;
@Value("${com.rocketmq.name}")
private String rocketmqName;
@GetMapping("/common")
public String show(){
return "mysqlName: " + mysqlName + ", redisName: " + redisName + ", rocketmqName: " + rocketmqName;
}
}
5. 变更 com.redis.name 时,应用程序中能够动态获取最新配置内容咯。