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: trueDemo1.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: nacosDemo1.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;
}
}