在 Spring Boot 中监听 Nacos 配置的变化,可以通过 @RefreshScope、@NacosConfigListener 或 编程式监听 的方式实现。以下是详细方法:
动态监听的方式
1. 使用 @RefreshScope + @Value(适用于简单配置)
适用于动态刷新 @Value 注解的配置项。
步骤
- 添加依赖(确保已引入 Nacos Config Starter):
12345<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${spring-cloud-alibaba.version}</version></dependency>
- 在
application.yml中配置 Nacos:
12345678spring:application:name: your-service-namecloud:nacos:config:server-addr: 127.0.0.1:8848file-extension: yaml # 配置格式(支持 properties/yaml)
- 在 Nacos 控制台创建配置:
- Data ID:
your-service-name.yaml(与spring.application.name一致) - Group:
DEFAULT_GROUP(默认) - 配置格式: YAML
- 内容示例:
12config:key: "initial-value"
- Data ID:
- 在代码中使用
@Value+@RefreshScope:
1234567891011121314151617import 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;@RestController@RefreshScope // 允许动态刷新public class ConfigController {@Value("${config.key}")private String configKey;@GetMapping("/config")public String getConfig() {return configKey;}}
- 测试动态刷新:
- 修改 Nacos 控制台中的
config.key值并发布。 - 调用
/actuator/refresh(需暴露端点)或直接访问/config接口,观察值是否更新。
- 修改 Nacos 控制台中的
2. 使用 @NacosConfigListener(推荐)
适用于监听特定 dataId 或 groupId 的配置变化,并执行自定义逻辑。
步骤
- 添加依赖(同上)。
- 编写监听器:
1234567891011121314151617import com.alibaba.nacos.api.config.annotation.NacosConfigListener;import org.springframework.stereotype.Component;@Componentpublic class NacosConfigListener {@NacosConfigListener(dataId = "your-service-name.yaml", // 监听的 Data IDgroupId = "DEFAULT_GROUP", // 监听的 Grouptype = ConfigType.YAML // 配置类型(YAML/PROPERTIES))public void onConfigChanged(String newConfig) {System.out.println("配置发生变化: " + newConfig);// 解析 YAML 并更新本地配置// 例如:使用 SnakeYAML 解析 newConfig}}
- 处理配置变更:
newConfig是变更后的完整配置内容(字符串)。- 可使用
SnakeYAML或Jackson解析 YAML/JSON。
3. 编程式监听(手动控制)
通过 ConfigService 直接监听配置变化。
步骤
- 注入
ConfigService:
12345678910111213141516171819202122232425262728import com.alibaba.nacos.api.config.ConfigService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class ManualNacosListener {@Autowiredprivate ConfigService configService;public void addListener() throws NacosException {configService.addListener("your-service-name.yaml","DEFAULT_GROUP",new Listener() {@Overridepublic void receiveConfigInfo(String configInfo) {System.out.println("配置变更: " + configInfo);}@Overridepublic Executor getExecutor() {return null; // 使用默认线程池}});}}
- 在应用启动时注册监听:
1234567891011121314import org.springframework.boot.ApplicationRunner;import org.springframework.stereotype.Component;@Componentpublic class NacosListenerInitializer implements ApplicationRunner {@Autowiredprivate ManualNacosListener manualNacosListener;@Overridepublic void run(ApplicationArguments args) throws Exception {manualNacosListener.addListener();}}
4. 结合 @ConfigurationProperties 动态刷新
适用于绑定复杂配置对象。
步骤
- 定义配置类:
1234567891011121314151617import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.stereotype.Component;@Component@RefreshScope@ConfigurationProperties(prefix = "config")public class MyConfig {private String key;private int timeout;// Getter & Setterpublic String getKey() { return key; }public void setKey(String key) { this.key = key; }public int getTimeout() { return timeout; }public void setTimeout(int timeout) { this.timeout = timeout; }}
- 在 Nacos 中配置:
123config:key: "dynamic-value"timeout: 5000
- 使用配置:
1234567891011@RestControllerpublic class ConfigController {@Autowiredprivate MyConfig myConfig;@GetMapping("/config")public MyConfig getConfig() {return myConfig; // 自动刷新}}
5. 暴露 actuator/refresh 端点(可选)
如果使用 @RefreshScope,需暴露刷新端点:
|
1 2 3 4 5 |
management: endpoints: web: exposure: include: refresh,health,info |
然后手动调用 /actuator/refresh 触发刷新(或通过消息总线自动触发)。
总结
| 方式 | 适用场景 | 特点 |
|---|---|---|
@RefreshScope + @Value |
简单配置项 | 需手动调用 /actuator/refresh |
@NacosConfigListener |
自定义监听逻辑 | 直接监听 dataId 变化 |
编程式 ConfigService |
完全手动控制 | 灵活但代码复杂 |
@ConfigurationProperties |
复杂配置对象 | 支持结构化配置 |
推荐:
- 简单场景用
@RefreshScope+@Value。 - 需要精细控制时用
@NacosConfigListener。 - 复杂对象用
@ConfigurationProperties。
ConfigService使用
在 Spring Boot 中,ConfigService 不会自动注入,因为它不是 Spring 容器默认管理的 Bean。你需要手动配置它,或者通过 Nacos 提供的 NacosConfigManager 来获取 ConfigService 实例。
解决方法
1. 通过 @Bean 手动注册 ConfigService
在 Spring Boot 中,可以通过 NacosConfigProperties 和 NacosConfigManager 来获取 ConfigService,然后手动将其注册为 Bean。
步骤
- 添加依赖(确保已引入 Nacos Config Starter):
12345<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${spring-cloud-alibaba.version}</version></dependency>
- 配置
ConfigServiceBean:
1234567891011121314151617import com.alibaba.nacos.api.config.ConfigService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.alibaba.cloud.nacos.NacosConfigProperties;@Configurationpublic class NacosConfig {@Autowiredprivate NacosConfigProperties nacosConfigProperties;@Beanpublic ConfigService configService() throws Exception {return nacosConfigProperties.configServiceInstance();}}
- 在代码中注入
ConfigService:
12345678910111213141516171819import com.alibaba.nacos.api.config.ConfigService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class AutoDelayJob {@Autowiredprivate ConfigService configService; // 现在可以正常注入public void someMethod() {try {String config = configService.getConfig("dataId", "group", 5000);System.out.println("配置内容: " + config);} catch (Exception e) {e.printStackTrace();}}}
2. 直接使用 NacosConfigManager(推荐)
Spring Cloud Alibaba Nacos 提供了 NacosConfigManager,它可以更方便地获取 ConfigService。
步骤
- 注入
NacosConfigManager:
1234567891011121314151617181920import com.alibaba.cloud.nacos.NacosConfigManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class AutoDelayJob {@Autowiredprivate NacosConfigManager nacosConfigManager; // 直接注入public void someMethod() {try {ConfigService configService = nacosConfigManager.getConfigService();String config = configService.getConfig("dataId", "group", 5000);System.out.println("配置内容: " + config);} catch (Exception e) {e.printStackTrace();}}}
3. 检查 Nacos 配置是否正确
如果仍然报错,请检查:
application.yml是否配置了 Nacos:
12345678spring:cloud:nacos:config:server-addr: 127.0.0.1:8848namespace: your-namespace-id # 可选group: DEFAULT_GROUP # 默认组file-extension: yaml # 配置格式- 是否引入了
spring-cloud-starter-alibaba-nacos-config。 - Nacos 服务器是否可访问(检查
server-addr是否正确)。
总结
| 方法 | 适用场景 | 优点 |
|---|---|---|
手动注册 ConfigService |
需要直接控制 ConfigService 实例 |
灵活,但需要额外配置 |
使用 NacosConfigManager |
推荐方式 | 简洁,Spring Cloud Alibaba 官方推荐 |
| 检查 Nacos 配置 | 基础问题排查 | 确保 Nacos 连接正常 |
推荐:
- 优先使用
NacosConfigManager,因为它已经由 Spring Cloud Alibaba 管理,无需手动注册。 - 如果遇到
ConfigService注入失败,检查 Nacos 配置是否正确,并确保依赖已引入。🚀