一、项目版本
<spring-boot.version>2.6.13</spring-boot.version>
<spring.cloud.version>2021.0.5</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version>
二、项目搭建
2.1、新建子模块 nacos-config
在父工程代码的基础上新建一个子模块,名字叫 nacos-config
记得在父工程添加模块
<modules> <module>nacos-config</module> </modules>
2.2、加入依赖
<dependencies>
<!--Spring Boot Web 场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Spring Cloud Alibaba Nacos 注册中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--Spring Cloud Alibaba Nacos 配置中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 新版本的 Nacos 不再依赖 Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--Spring Boot 测试场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
2.3、修改 application.yml
server:
port: 8040
spring:
cloud:
nacos:
discovery:
username: nacos
password: nacos
server-addr: 127.0.0.1:8848
config:
username: nacos
password: nacos
server-addr: 127.0.0.1:8848
namespace: dev # 命名空间
application:
name: nacos-config-service
config:
import:
- optional:nacos:${spring.application.name}.properties
Nacos 配置中心配置方式变化:
- 在SpringBoot 2.4 这个大版本中有一项非常重要的改进,出于对云原生多配置文件的支持,默认关闭了对 bootstrap.yml 的使用。统一都在 application.yml 配置。
- spring.config.import: -optional:nacos:${spring.application.name}.properties 这一行是 Spring Boot 2.4 及以上版本引入的配置文件导入机制,optional:nacos:${spring.application.name}.properties 表示从 Nacos 配置中心导入名为 nacos-config-service.properties 的配置文件,其中 optional 关键字意味着如果该配置文件在 Nacos 中不存在,那么 Spring Boot 将不会抛出异常,而是继续执行后续的初始化流程。
2.4、新建一个 Controller
@RestController
@RequestMapping("/nacos-config")
public class NacosConfigController {
private final Environment environment;
@Autowired
public NacosConfigController(Environment environment) {
this.environment = environment;
}
@RequestMapping("/readConfig")
public String readConfig() {
String username = environment.getProperty("custom.username");
String password = environment.getProperty("custom.password");
return "用户名[" + username + "],密码[" + password + "]";
}
}
- Nacos 客户端从 Nacos 配置中心拉取到配置后,会把配置信息设置到 Environment.propertySources 中。
- Environment 是 Spring Core 提供给应用的一个核心接口,它代表了当前应用程序运行的环境。此接口提供了对应用程序运行时的配置信息(如 application.properties 或 application.yml)、操作系统的环境变量、Java 系统属性等的访问。
2.5、配置中心配置
2.5.1、在 Nacos 新建一个 dev 命名空间
2.5.2、在 dev 命名空间中创建配置
官方推荐,Data Id 的配置格式为:
配置内容为:
custom.username=Lin
custom.password=456
2.6、访问测试
localhost:8040/nacos-config/readConfig
可以看到配置信息被正确读取到。
2.7、时效性测试
2.7.1、修改配置信息并发布
custom.username=Lin
custom.password=123 # 456->123
可以看到配置信息几乎实时被修改。
Nacos 配置中心的配置数据发生变更,可以通过推或者拉的方式(默认是推),实时地更新到客户端 Environment.propertySources 中。
三、配置的优先级
使用 import 方式导入的配置,配置的优先级按 import 顺序加载,如果有重复的配置项,后面的会覆盖前面的。
3.1、使用克隆方式重新创建一个配置 nacos-config-service2.properties
3.2、修改 nacos-config-service2.properties 配置内容
custom.username=Lin2
3.3、在 application.yml 中 import nacos-config-service2.properties
3.4、访问测试
重启服务,访问测试 localhost:8040/nacos-config/readConfig
可以看出 nacos-config-service2.properties 的 custom.username 覆盖了 nacos-config-service.properties 的 custom.username,但 custom.password 却没变,因为 custom.password 配置项没有重复。
可以把它理解为往 Environment.propertySources 里面 set 值,key 相同的会被覆盖。
四、@Value 注入
4.1、修改一下 Controller
以 @Value 注解的方式注入配置属性:
@RestController
@RequestMapping("/nacos-config")
public class NacosConfigController {
@Value("${custom.username}")
private String userName;
@Value("${custom.password}")
private String passWord;
private final Environment environment;
@Autowired
public NacosConfigController(Environment environment) {
this.environment = environment;
}
@RequestMapping("/readConfig")
public String readConfig() {
String username = environment.getProperty("custom.username");
String password = environment.getProperty("custom.password");
return "Environment中用户名[" + username + "],密码[" + password + "]; " +
"属性中用户名[" + userName + "],密码[" + passWord + "];";
}
}
4.2、访问测试
localhost:8040/nacos-config/readConfig
可以看到 @Value 注解同样可以注入配置属性。
4.3、时效性测试
修改 nacos-config-service2.properties 配置内容
custom.username=Wang
再次访问:
@Value 注入的属性值并没有变化
这是因为,@Value 只在 Bean 初始化的时候,从 Environment.propertySources 获取配置参数,注入属性。之后就再也没变化了。
4.4、添加 @RefreshScope 注解
@RefreshScope
@RestController
@RequestMapping("/nacos-config")
public class NacosConfigController {
}
重启服务,再次修改 nacos-config-service2.properties 配置内容
custom.username=Zeng
@RefreshScope 原理:
@RefreshScope 修饰的 Bean 的属性发生变化后,会从IOC缓存中被清除。等到下一次被调用的时候,再重新初始化一个新的 Bean,重新初始化的 Bean,属性重新从 Environment.propertySources 获取,这个时候获取到的就是最新的配置数据。
五、官方案例
spring.cloud.alibaba.com 已移步到 sca.aliyun.com,所以官方案例移步到此。
注意选择自己的版本。