简介
我们在开发的时候,可能会遇到这样的场景:
变量希望能够被在配置文件中动态配置,只要修改这些配置,对应的 Java 类对象的变量值就可以改变,从而改变代码的行为。这样我们通过修改配置就可以满足业务诉求,而不需要修改一行代码。
在 SpringBoot 中,可以通过 @ConfigurationProperties
和 @Values
两个注解配合 properties 文件达到上述目的。
比如我的 application.properties
文件配置如下:
# ------------------------
# Swagger config
# ------------------------
msconfig.swagger.enableSwagger=true
# ------------------------
# Security config
# ------------------------
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
的代码如下:
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;
// List的配置
private List testList;
// Map的配置
private Map testMap;
}
这里需要注意以下几个问题:
1、必须提供 setter 方法,这里我使用了 lombok
;
2、必须使用 @Component
注解,标注在实体类上面;
3、在 @ConfigurationProperties
的 prefix
中必须和配置文件命名保持一致;
4、需要在类上加上 @Component
注解;
关于 MSSwaggerPropertyConfigModel
大家可以自行查看代码,这里不再赘述。
写个测试类,验证一下配置。
@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);
}
}
执行该测试方法,得到如下的输出内容:
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
注解过程中,提示如下错误:
“Spring Boot Configuration Annotation Processor not found in classpath ”
此时需要在你的 pom.xml
文件中引进 configuration-processor
依赖即可解决。
<!--ConfigurationProperties-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Value
使用 @Values
注解可以直接作用到某个类的某个字段上面,使用上面比较方便。
对于读取集合的方法跟 @ConfigurationProperties
注解有点不同。
在 application.properties
文件中增加 testList1
和 testMap1
配置如下:
# ------------------------
# Security config
# ------------------------
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
注解对集合的书写格式。
@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);
}
读取结果如下:
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
这两个注解配合使用。
msconfig.security.alias="play-game"
在代码中重新定义变量名称为 aliasPlayGame
,可以使用 @Values
定位实际配置的变量名称。
@Component
@Setter
@Getter
@ConfigurationProperties(prefix = "msconfig.security")
public class MSSecurityPropertyConfigModel {
private boolean enableCSRF;
private String defToken;
private List testList;
private Map testMap;
// 和 ConfigurationProperties 一起使用
@Value("msconfig.security.alias")
private String aliasPlayGame;
}
你以为的不一定是你以为的