测试环境中的配置文件
application.yml
spring:
profiles:
active: prod
application-prod.yml
server:
port: 8030
application-sit.yml
server:
port: 8031
1.Environment
Spring中有一个类Environment,它可以被认为是当前应用程序正在运行的环境,它继承了PropertyResolver接口,因此可以作为一个属性解析器使用。
@RestController
@RequestMapping("/yml")
public class YmlController {
@Autowired
private Environment environment;
@RequestMapping(value = "environmentGetYmlProperty",method = RequestMethod.GET)
public Object environmentGetYmlProperty(){
//拿到所有被激活的配置文件
String[] activeProfiles = environment.getActiveProfiles();
for (String activeProfile : activeProfiles) {
System.out.println(activeProfile);
}
String propertyStr = environment.getProperty("server.port");
Integer propertyInt = environment.getProperty("server.port",Integer.class);
String propertyNull = environment.getProperty("server.portNull",String.class,"defaultValue");
System.out.println(propertyStr);
System.out.println(propertyInt);
System.out.println(propertyNull);
return "test ok";
}
}
控制台输出结果为:
prod
8030
8030
defaultValue
2.YamlPropertiesFactoryBean自定义配置的yml文件读取
需要通过setResources()方法设置自定义yml配置文件的存储路径,再通过getObject()方法获取Properties对象,后续就可以通过它获取具体的属性
application-custom.yml
hc:
name: hc
age: 22
@GetMapping("customGetYmlProperty")
public Object customGetYmlProperty(){
YamlPropertiesFactoryBean customYmlBean= new YamlPropertiesFactoryBean();
customYmlBean.setResources(new ClassPathResource("application-custom.yml"));
Properties properties = customYmlBean.getObject();
System.out.println(properties.get("hc.name"));
System.out.println(properties.get("hc.age"));
System.out.println(properties.toString());
return "test ok";
}
控制台输出:
hc
22
{hc.age=22, hc.name=hc}
但是这样的使用中有一个问题, 那就是只有在这个接口的请求中能够取到这个属性的值,如果再写一个接口,不使用YamlPropertiesFactoryBean读取配置文件,即使之前的方法已经读取过这个yml文件一次了,第二个接口取到的仍然还是空值。
想要解决这个问题也很简单,可以配合PropertySourcesPlaceholderConfigurer使用,它实现了BeanFactoryPostProcessor接口,也就是一个bean工厂后置处理器的实现,可以将配置文件的属性值加载到一个Properties文件中。
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
@Configuration
public class PropertyConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer
= new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yamlProFb
= new YamlPropertiesFactoryBean();
yamlProFb.setResources(new ClassPathResource("application-custom.yml"));
configurer.setProperties(yamlProFb.getObject());
return configurer;
}
}
@Value("${hc.name:null}")
private String name;
@Value("${hc.age:null}")
private Integer age;
@GetMapping("customGetYmlProperty2")
public Object customGetYmlProperty2() {
System.out.println(name);
System.out.println(age);
return "test ok";
}
调用接口后控制台输出:
hc
22
除了使用YamlPropertiesFactoryBean将yml解析成Properties外,其实我们还可以使用YamlMapFactoryBean解析yml成为Map,使用方法非常类似:
3.监听事件
SpringBoot是通过监听事件的方式来加载和解析的yml文件,定义一个类实现ApplicationListener接口,监听的事件类型为ApplicationEnvironmentPreparedEvent,并在构造方法中传入要解析的yml文件名,自定义的监听器中需要实现接口的onApplicationEvent()方法,当监听到ApplicationEnvironmentPreparedEvent事件时会被触发:
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import java.io.IOException;
import java.util.List;
public class YmlListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private String ymlFilePath;
public YmlListener(String ymlFilePath) {
this.ymlFilePath = ymlFilePath;
}
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
ResourceLoader loader = new DefaultResourceLoader();
YamlPropertySourceLoader ymlLoader = new YamlPropertySourceLoader();
try {
List<PropertySource<?>> sourceList = ymlLoader
.load(ymlFilePath, loader.getResource(ymlFilePath));
for (PropertySource<?> propertySource : sourceList) {
environment.getPropertySources().addLast(propertySource);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
上面的代码中,主要实现了:
获取当前环境Environment,当ApplicationEnvironmentPreparedEvent事件被触发时,已经完成了Environment的装载,并且能够通过event事件获取
通过YamlPropertySourceLoader加载、解析配置文件
将解析完成后的OriginTrackedMapPropertySource添加到Environment中
修改启动类,在启动类中加入这个监听器:
import com.midea.cloud.blog.listener.YmlListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(BlogApplication.class);
application.addListeners(new YmlListener("classpath:/application-custom.yml"));
application.run(args);
}
}