微服务: ConfigurationProperties配置
简介
我们在开发的时候,可能会遇到这样的场景:
变量希望能够被在配置文件中动态配置,只要修改这些配置,对应的 Java 类对象的变量值就可以改变,从而改变代码的行为。这样我们通过修改配置就可以满足业务诉求,而不需要修改一行代码。
在 SpringBoot 中,可以通过 @ConfigurationProperties
和 @Values
两个注解配合 properties 文件达到上述目的。
比如我的 application.properties
文件配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
msconfig.swagger.enableSwagger=true
msconfig.security.enableCSRF=false msconfig.security.defToken="token-xx-yy-kk-token-end"
msconfig.security.testList[0]="list0" msconfig.security.testList[1]="list1" msconfig.security.testList[2]="list2"
msconfig.security.testMap.KeyTest="map-key" msconfig.security.testMap.ValueTest="map-value"
|
接下来,通过 @ConfigurationProperties
和 @Values
来分别读取对应的配置。
本文涉及的代码都已经更新到 Github 工程 中了,大家可以下载查看。
关于微服务的相关文章目录,可以☞ 点我 查看更多内容。
ConfigurationProperties
对应的,新建两个实体类,如下图所示:
实体类 MSSecurityPropertyConfigModel
的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;
import java.util.List; import java.util.Map;
@Component @Setter @Getter @ConfigurationProperties(prefix = "msconfig.security") public class MSSecurityPropertyConfigModel { private boolean enableCSRF;
private String defToken;
private List testList;
private Map testMap; }
|
这里需要注意以下几个问题:
1、必须提供 setter 方法,这里我使用了 lombok
;
2、必须使用 @Component
注解,标注在实体类上面;
3、在 @ConfigurationProperties
的 prefix
中必须和配置文件命名保持一致;
4、需要在类上加上 @Component
注解;
关于 MSSwaggerPropertyConfigModel
大家可以自行查看代码,这里不再赘述。
写个测试类,验证一下配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @RunWith(SpringRunner.class) @SpringBootTest public class MSPropertyConfigTests {
@Autowired MSSwaggerPropertyConfigModel swaggerPropertyConfigModel;
@Autowired MSSecurityPropertyConfigModel securityPropertyConfigModel;
private Logger logger = LoggerFactory.getLogger(MSPropertyConfigTests.class);
@Test public void primitiveDataConfig() {
boolean enableSwagger = swaggerPropertyConfigModel.isEnableSwagger(); boolean enableCSRF = securityPropertyConfigModel.isEnableCSRF();
logger.info("primitiveDataConfig-enableSwagger: " + enableSwagger + ", enableCSRF: " + enableCSRF);
String defToken = securityPropertyConfigModel.getDefToken(); logger.info("securityPropertyConfigModel deftoken: " + defToken);
List list = securityPropertyConfigModel.getTestList(); for (Object v : list) { logger.info("securityPropertyConfigModel value: " + v); }
Map map = securityPropertyConfigModel.getTestMap(); logger.info("securityPropertyConfigModel map: " + map); } }
|
执行该测试方法,得到如下的输出内容:
1 2 3 4 5 6
| primitiveDataConfig-enableSwagger: true, enableCSRF: false securityPropertyConfigModel deftoken: "token-xx-yy-kk-token-end" securityPropertyConfigModel value: "list0" securityPropertyConfigModel value: "list1" securityPropertyConfigModel value: "list2" securityPropertyConfigModel map: {KeyTest="map-key", ValueTest="map-value"}
|
如果您在使用 @ConfigurationProperties
注解过程中,提示如下错误:
1
| “Spring Boot Configuration Annotation Processor not found in classpath ”
|
此时需要在你的 pom.xml
文件中引进 configuration-processor
依赖即可解决。
1 2 3 4 5 6
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
|
Value
使用 @Values
注解可以直接作用到某个类的某个字段上面,使用上面比较方便。
对于读取集合的方法跟 @ConfigurationProperties
注解有点不同。
在 application.properties
文件中增加 testList1
和 testMap1
配置如下:
1 2 3 4 5 6 7 8 9
|
msconfig.security.enableCSRF=false msconfig.security.defToken="token-xx-yy-kk-token-end"
msconfig.security.testList1=list0,list1,list2 msconfig.security.testMap1={name:"map-key", age:20}
|
注意:在配置文件中的 testList1
和 testMap1
配置格式和之前的不一样,否则解析会报错。
测试类中验证,示例代码如下,注意 @Values
注解对集合的书写格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Value("${msconfig.security.enableCSRF}") private boolean geEnableCSRF;
@Value("${msconfig.security.defToken}") private String defUserToken;
@Value("#{'${msconfig.security.testList1}'.split(',')}") private List list1;
@Value("#{${msconfig.security.testMap1}}") private Map map1;
@Test public void primitiveDataConfig() { logger.info("annotation value. geEnableCSRF: " + geEnableCSRF); logger.info("annotation value. defUserToken: " + defUserToken);
for (Object v : list1) { logger.info("annotation value. list: " + v); }
logger.info("annotation value. map: " + map1); }
|
读取结果如下:
1 2 3 4 5 6
| annotation value. geEnableCSRF: false annotation value. defUserToken: "token-xx-yy-kk-token-end" annotation value. list: list0 annotation value. list: list1 annotation value. list: list2 annotation value. map: {name=map-key, age=20}
|
我们也可以将 @ConfigurationProperties
和 @Values
这两个注解配合使用。
1
| msconfig.security.alias="play-game"
|
在代码中重新定义变量名称为 aliasPlayGame
,可以使用 @Values
定位实际配置的变量名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Component @Setter @Getter @ConfigurationProperties(prefix = "msconfig.security") public class MSSecurityPropertyConfigModel { private boolean enableCSRF;
private String defToken;
private List testList;
private Map testMap;
@Value("msconfig.security.alias") private String aliasPlayGame; }
|
你以为的不一定是你以为的