手机用户请
横屏
获取最佳阅读体验,REFERENCES
中是本文参考的链接,如需要链接和更多资源,可以关注其他博客发布地址。
平台 | 地址 |
---|---|
CSDN | https://blog.csdn.net/sinat_28690417 |
简书 | https://www.jianshu.com/u/3032cc862300 |
个人博客 | https://yiyuery.club |
分享整理 Spring Boot 下的配置文件加载
DEV-ENV
Spring Boot: 2.1.0
JDK: 1.8
主要分成以下几个方面来介绍下使用和配置方式:
1、 @Value
方式加载 application.yaml
中配置
application.yaml 中配置项
props:
db-name: db_capsule
测试
@Value("${props.db-name}")
private String dbName;
@Test
public void testX1(){
System.out.println(dbName);
}
2、 @PropertySource(value="classpath:props.properties")
方式
props.properties 中配置项
a.b=1
@Configuration
@PropertySource("classpath:conf/props.properties")
public class PropertiesLoader {
@Value("${a.b}")
private Integer ab;
@Bean
public Integer ab(){
return ab;
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {
@Resource(name="ab")
private Integer ab;
@Test
public void testX1(){
System.out.println(ab);
}
}
1、 配置 PropertyPlaceholderConfigurer
在项目外指定目录下新增一个properties文件
@Configuration
public class ResourceLoader {
@Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setLocation(new FileSystemResource(Paths.get("/Users/xiazhaoyang/Documents/capsule/architectrue-adventure/conf/props.properties")));
//此处亦可添加项目路径下资源,使用ClassPathResource即可
return configurer;
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {
@Resource(name="ab")
private Integer ab;
@Value("${a.b.c}")
private Integer abc;
@Test
public void testX1(){
System.out.println(ab);
System.out.println(abc);
}
}
1、 实例对象成员属性自动注入
person:
auto:
name: x1
age: 18
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person.auto")
public class PersonAutoConfig {
private String name;
private Integer age;
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {
@Resource
private PersonAutoConfig personAutoConfig;
@Test
public void testX1(){
//...
System.out.println(personAutoConfig.toString());
//...
}
}
2、 实例集合属性自动注入
person:
auto:
name: x1
age: 18
list:
personList:
- name: x2
age: 19
- name: x3
age: 20
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person.list")
public class PersonListAutoConfig {
private List<PersonAutoConfig> personList;
}
测试
@Resource
private PersonListAutoConfig personListAutoConfig;
@Test
public void testX1(){
System.out.println(personListAutoConfig);
}
@Bean
@Primary
public CapPropertyPlaceholderConfigurer propertyConfigurer() throws IOException {
CapPropertyPlaceholderConfigurer configurer = new CapPropertyPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
//加载本地外部配置的yaml,也可以选择项目内
yaml.setResources(new FileSystemResource(Paths.get(RunnerMonitor.getEnvConfPath().getConfPath(), "config.yaml").toFile()));
Properties props = new Properties();
props.putAll(Objects.requireNonNull(yaml.getObject()));
//项目内 properties 配置文件加载
props.load(PropertiesLoaderSupport.class.getResourceAsStream("/constants.properties"));
configurer.setProperties(props);
configurer.setFileEncoding(BasicConstants.DEFAULT_ENCODING);
return configurer;
}
CapPropertyPlaceholderConfigurer
public class CapPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer{
private Properties capProps;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
capProps = props;
}
/**
* 自定义配置获取,对外提供入口
* @return
*/
public Properties getCapProps() {
return capProps;
}
}
此处主要实现本地和外部配置文件加载的功能,并提供出口,在其他地方注入实例 CapPropertyPlaceholderConfigurer
即可获取到对应自定义的配置属性信息
今天在做一个功能开发的时候,发现加载的配置,在 Environment
实例中一直获取不到对应的配置属性,为此特地做个测试。
首先,外部 props
文件展示下,方便比对
x.a.b=1
x.a.b.c=2
所以内外配置项各不相同,然后内部原有的配置变量 a.b=123
删除掉,在外部 props
中增加 a.b=321
的配置,接下来我们 测试下输出
@Value("${a.b.c}")
private Integer abc;
@Value("${x.a.b.c}")
private Integer xabc;
@Value("${x.a.b}")
private Integer xab;
@Resource
private Environment environment;
@Test
public void testX1(){
System.out.println(abc);
System.out.println(xab);
System.out.println(xabc);
System.out.println(environment.getProperty("a.b"));
System.out.println(environment.getProperty("x.a.b"));
System.out.println(environment.getProperty("x.a.b.c"));
}
通过输出可以看出通过 PropertyPlaceholderConfigurer
或其子类加载的配置,是不会写入到 Environment
实例的。
此处需要 注意
,由于配置了 PropertyPlaceholderConfigurer
,需要注意在加载配置的时候,需要设置 ignore-unresolvable
为true,不然会报 a.b
无法通过${a,b}解析获取的错误
@Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setIgnoreUnresolvablePlaceholders(true);
configurer.setLocation(new FileSystemResource(Paths.get("/Users/xiazhaoyang/Documents/capsule/architectrue-adventure/conf/props.properties")));
return configurer;
}
2019-07-28 19:00:54.801 INFO 72049 --- [ main] e.c.b.s.CommonBootSupportApplicationTest : Started CommonBootSupportApplicationTest in 4.303 seconds (JVM running for 6.642)
321
1
2
null
null
null
那么,如果项目外定义的变量和项目内重复又会怎么样呢?我们在项目内 props
配置文件中还原 a.b=123
配置属性,测试下输出
321
1
2
123
null
null
显然, Environment
实例获取到的是项目内的配置项,和外部配置文件加载互不干扰。
所以该小节结论是外部通过 PropertyPlaceholderConfigurer
注入的参数配置不会影响到 Environment
获取的配置数据,如果想用自身配置项的话,需要自定义处理类,比如继承指定接口,或是通过配置项,将项目依赖的 Environment
获取配置项的方式转换到自身配置类。
好了,中心思想来了哦。总结下今天的整理,首先,我们了解了Spring Boot 中配置 文件的几种加载方式。然后呢?1、通过 @Value
在注入类的实例中直接定义变量从 applicaition.yaml
中获取 2、通过注解 @Configuration
和 @PropertySource("classpath:conf/props.properties")
获取项目内其他路径的配置文件 3、怎么给注入的实例自动填充配置参数(集合和对象中的普通参数) 4、yaml配置文件的加载 5、外部配置文件的加载方式 6、外部配置文件加载和 Environment
获取配置参数的方式是互不干扰的,如果需要改写某个类的实现,原来依赖于 Environment
,但是需要调整为自定义的外部配置的话,需要自定义实现,比方说 jasypt
的加密密钥,原生的方法使用的是项目内的配置文件,且是通过 Environment
获取的。但是对于密钥这种敏感信息,我们一般是不放在项目代码中的,安全性需要保证,就需要自定义配置参数和加载路径。7、最后特别注意下如果配置了 PropertyPlaceholderConfigurer
时最好是开启 configurer.setIgnoreUnresolvablePlaceholders(true);
,不然遇到解析不到的属性就会报错。