Nacos 配置自动刷新是指在 Nacos 中的配置文件变更后,应用程序(微服务)无需重启就可以感知。下面将介绍在 Spring Boot 和 Spring Cloud 项目中如何实现配置自动刷新。
@NacosValue 注解是 Nacos 提供的注解,它允许您动态地从 Nacos 中注入配置值。通过使用 @NacosValue,您可以轻松地检索和更新配置值,而无需重新启动应用程序。例如:
pom.xml 依赖
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version>0.2.7</version> </dependency>
application.yml
server: port: 8080 spring: application: name: nacos_spring_boot_demo # nacos相关配置 nacos: config: bootstrap: # 开启系统启动时预读取 nacos 的配置,用于满足 @Value 注入数据的场景 enable: true # 配置所属命名空间的 id,此处我们配置名称为 dev 的 id,可以在命名空间列表查看 id 的值 namespace: 8719efd1-94a6-49f7-9846-2debd66f6c0f # 配置所属分组 group: DEFAULT_GROUP # 配置ID data-id: nacos_spring_boot_demo # 配置文件类型,对应 nacos 配置页面的配置格式,默认是 properties type: yaml # nacos 服务器地址 server-addr: 127.0.0.1:8848 username: nacos password: nacos # 开启自动刷新 nacos 配置 # 注意,需要使用 @NacosValue 注解,并且 autoRefreshed 必须设置为 true auto-refresh: true # 针对配置项同名的情况,是否允许 nacos 的配置覆盖本地的配置 remote-first: true
Demo1.java
package com.hxstrive.nacos; import com.alibaba.nacos.api.config.annotation.NacosValue; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * 利用 @NacosValue 或 @Value 注入配置信息 * @author hxstrive.com */ @RestController public class Demo1 { // 可以实现自动刷新 @NacosValue(value = "${demo.title}", autoRefreshed = true) private String nacosValueTitle; // 不能自动刷新 @Value("${demo.title}") private String title; @GetMapping("/demo1") public Demo1 demo1() { return this; } public String getNacosValueTitle() { return nacosValueTitle; } public String getTitle() { return title; } }
ConfigurableApplicationContext 是 Spring Framework 中的一个接口,它扩展了 ApplicationContext 接口,提供了一些额外的方法,用于配置和管理应用程序上下文的生命周期和属性。例如:
pom.xml 依赖
<!-- @ConfigurationProperties 需要 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
application.yml
同上面配置
Demo3.java
package com.hxstrive.nacos; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * 获取配置,自动刷新 * @author hxstrive.com */ @RestController public class Demo3 { @Autowired private ConfigurableApplicationContext applicationContext; @GetMapping("/demo3") public String demo3() { // 可以感知配置的变化,每次获取最新的配置 return applicationContext.getEnvironment().getProperty("demo.title"); } }
@RefreshScope 是 Spring Cloud 中的一个注解,用于实现动态刷新配置的功能。当使用 @RefreshScope 注解标记一个 Bean 时,Spring Cloud 会自动将该 Bean 包装在一个代理对象中,并在代理对象被访问时检查是否需要刷新配置。例如:
pom.xml
<dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- Spring Boot Begin --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- @ConfigurationProperties 需要 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot End --> <!-- Spring Cloud Begin --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- Spring Cloud End --> </dependencies>
application.yml
server: port: 8080 spring: application: # 应用名称,用来匹配 Nacos 中的配置集 # 默认将根据下面指定的 spring.cloud.config.namespace + spring.cloud.config.group + spring.application.name + file-extension # 进行匹配,例如:当前应用将匹配 # 8719efd1-94a6-49f7-9846-2debd66f6c0f 命名空间中 DEFAULT_GROUP 分组下 # 名为 nacos_spring_cloud 且格式为 yaml 的配置集 name: nacos_spring_cloud_demo cloud: nacos: config: # Nacos 服务地址 server-addr: 127.0.0.1:8848 # Nacos 配置文件扩展名 file-extension: yaml # Nacos 命名空间ID namespace: 8719efd1-94a6-49f7-9846-2debd66f6c0f # Nacos 分组 group: DEFAULT_GROUP # Nacos 登录账号 username: nacos # Nacos 登录密码 password: nacos
Demo1.java
package com.hxstrive.nacos; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * 通过 @RefreshScope 注解实现配置自动刷新 * @author hxstrive.com */ @RestController @RefreshScope public class Demo1 { @Value("${demo.title}") private String title; @GetMapping("/demo1") public String demo1() { return title; } }
@ConfigurationProperties 是一个 Spring Boot 注解,用于将配置文件中的属性值绑定到 Java 对象上。通过使用 @ConfigurationProperties 注解,可以方便地将配置文件中的属性值注入到应用程序中的相应属性中。注意,在 Spring Boot 项目中不能实现自动刷新,在 Spring Cloud 项目中可以实现自动刷新。例如:
pom.xml
同上
application.yml
同上
Demo2.java
package com.hxstrive.nacos; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * 使用 @ConfigurationProperties 注解实现配置自动加载 * @author hxstrive.com */ @RestController @ConfigurationProperties(prefix = "demo") public class Demo2 { private String title; @GetMapping("/demo2") public String demo2() { return title; } public void setTitle(String title) { this.title = title; } }