在Spring中有一个类Environment,它可以被认为是当前应用程序正在运行的环境,它继承了PropertyResolver接口,因此可以作为一个属性解析器使用。先创建一个yml文件,属性如下:
我们提供的服务有:成都网站建设、做网站、微信公众号开发、网站优化、网站认证、洛浦ssl等。为上千余家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的洛浦网站制作公司
person:
name: hydra
gender: male
age: 18
使用起来也非常简单,直接使用@Autowired就可以注入到要使用的类中,然后调用它的getProperty()方法就可以根据属性名称取出对应的值了。
@RestController
public class EnvironmentController {
@Autowired
private Environment environment;
@GetMapping("envTest")
private void getEnv(){
System.out.println(environment.getProperty("person.name"));
System.out.println(environment.getProperty("person.gender"));
Integer autoClose = environment
.getProperty("person.age", Integer.class);
System.out.println(autoClose);
String defaultValue = environment
.getProperty("person.other", String.class, "defaultValue");
System.out.println(defaultValue);
}
}
在上面的例子中可以看到,除了简单的获取外,Environment提供的方法还可以对取出的属性值进行类型转换、以及默认值的设置,调用一下上面的接口,打印结果如下:
hydra
male
18
defaultValue
除了获取属性外,还可以用来判断激活的配置文件,我们先在application.yml中激活pro文件:
spring:
profiles:
active: pro
可以通过acceptsProfiles方法来检测某一个配置文件是否被激活加载,或者通过getActiveProfiles方法拿到所有被激活的配置文件。测试接口:
@GetMapping("getActiveEnv")
private void getActiveEnv(){
System.out.println(environment.acceptsProfiles("pro"));
System.out.println(environment.acceptsProfiles("dev"));
String[] activeProfiles = environment.getActiveProfiles();
for (String activeProfile : activeProfiles) {
System.out.println(activeProfile);
}
}
打印结果:
true
false
pro
在Spring中还可以使用YamlPropertiesFactoryBean来读取自定义配置的yml文件,而不用再被拘束于application.yml及其激活的其他配置文件。
在使用过程中,只需要通过setResources()方法设置自定义yml配置文件的存储路径,再通过getObject()方法获取Properties对象,后续就可以通过它获取具体的属性,下面看一个例子:
@GetMapping("fcTest")
public void ymlProFctest(){
YamlPropertiesFactoryBean yamlProFb = new YamlPropertiesFactoryBean();
yamlProFb.setResources(new ClassPathResource("application2.yml"));
Properties properties = yamlProFb.getObject();
System.out.println(properties.get("person2.name"));
System.out.println(properties.get("person2.gender"));
System.out.println(properties.toString());
}
查看运行结果,可以读取指定的application2.yml的内容:
susan
female
{person2.age=18, person2.gender=female, person2.name=susan}
但是这样的使用中有一个问题,那就是只有在这个接口的请求中能够取到这个属性的值,如果再写一个接口,不使用YamlPropertiesFactoryBean读取配置文件,即使之前的方法已经读取过这个yml文件一次了,第二个接口取到的仍然还是空值。来对这个过程进行一下测试:
@Value("${person2.name:null}")
private String name;
@Value("${person2.gender:null}")
private String gender;
@GetMapping("fcTest2")
public void ymlProFctest2(){
System.out.println(name);
System.out.println(gender);
}
先调用一次fcTest接口,再调用fcTest2接口时会打印null值:
null
null
想要解决这个问题也很简单,可以配合PropertySourcesPlaceholderConfigurer使用,它实现了BeanFactoryPostProcessor接口,也就是一个bean工厂后置处理器的实现,可以将配置文件的属性值加载到一个Properties文件中。使用方法如下:
@Configuration
public class PropertyConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer
= new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yamlProFb
= new YamlPropertiesFactoryBean();
yamlProFb.setResources(new ClassPathResource("application2.yml"));
configurer.setProperties(yamlProFb.getObject());
return configurer;
}
}
再次调用之前的接口,结果如下,可以正常的取到application2.yml中的属性:
susan
female
除了使用YamlPropertiesFactoryBean将yml解析成Properties外,其实我们还可以使用YamlMapFactoryBean解析yml成为Map,使用方法非常类似:
@GetMapping("fcMapTest")
public void ymlMapFctest(){
YamlMapFactoryBean yamlMapFb = new YamlMapFactoryBean();
yamlMapFb.setResources(new ClassPathResource("application2.yml"));
Mapmap = yamlMapFb.getObject();
System.out.println(map);
}
打印结果:
{person2={name=susan, gender=female, age=18}}
在上篇介绍原理的文章中,我们知道SpringBoot是通过监听事件的方式来加载和解析的yml文件,那么我们也可以仿照这个模式,来加载自定义的配置文件。
首先,定义一个类实现ApplicationListener接口,监听的事件类型为ApplicationEnvironmentPreparedEvent,并在构造方法中传入要解析的yml文件名:
public class YmlListener implements
ApplicationListener{
private String ymlFilePath;
public YmlListener(String ymlFilePath){
this.ymlFilePath = ymlFilePath;
}
//...
}
自定义的监听器中需要实现接口的onApplicationEvent()方法,当监听到ApplicationEnvironmentPreparedEvent事件时会被触发:
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
ResourceLoader loader = new DefaultResourceLoader();
YamlPropertySourceLoader ymlLoader = new YamlPropertySourceLoader();
try {
List> sourceList = ymlLoader
.load(ymlFilePath, loader.getResource(ymlFilePath));
for (PropertySource propertySource : sourceList) {
environment.getPropertySources().addLast(propertySource);
}
} catch (IOException e) {
e.printStackTrace();
}
}
上面的代码中,主要实现了:
修改启动类,在启动类中加入这个监听器:
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.addListeners(new YmlListener("classpath:/application2.yml"));
application.run(args);
}
在向environment中添加propertySource前加一个断点,查看环境的变化:
执行完成后,可以看到配置文件源已经被添加到了环境中:
启动完成后再调用一下接口,查看结果:
susan
female
能够正确的取到配置文件中的值,说明自定义的监听器已经生效。
前面介绍的几种方式,在Spring环境下无需引入其他依赖就可以完成的,接下来要介绍的SnakeYml在使用前需要引入依赖,但是同时也可以脱离Spring环境单独使用。先引入依赖坐标:
org.yaml
snakeyaml
1.23
准备一个yml配置文件:
person1:
name: hydra
gender: male
person2:
name: susan
gender: female
在使用SnakeYml解析yml时,最常使用的就是load、loadlAll、loadAs方法,这三个方法可以加载yml文件或字符串,最后返回解析后的对象。我们先从基础的load方法开始演示:
public void test1(){
Yaml yaml=new Yaml();
Mapmap =
yaml.load(getClass().getClassLoader()
.getResourceAsStream("snake1.yml"));
System.out.println(map);
}
运行上面的代码,打印Map中的内容:
{person1={name=hydra, gender=male}, person2={name=susan, gender=female}}
接下来看一下loadAll方法,它可以用来加载yml中使用---连接符连接的多个文档,将上面的yml文件进行修改:
person1:
name: hydra
gender: male
---
person2:
name: susan
gender: female
在添加了连接符后,尝试再使用load方法进行解析,报错如下显示发现了另一段yml文档从而无法正常解析:
这时候修改上面的代码,使用loadAll方法:
public void test2(){
Yaml yaml=new Yaml();
Iterable