1:写在前面
在工程上,不同的环境配置信息一般都是不一样的,之前常见的做法是,人工干预,在每个环境都手动修改,或者是放到外部文件中,这两种方式都有一个缺点,那就是容易出错,特别是第一种人工干预修改的方式,因此目前是通过每个环境定义一个配置文件的方式来解决这个问题,然后通过环境变量来控制启用哪个配置文件,本文我们就来通过ProperyPlaceholderConfigurer来实现这个功能。
另外,对于源码感兴趣的朋友可以参考这里。
2:多环境案例
2.1:定义配置文件
- application-dev.properties
my.name=dev环境的name
- application-prod.properties
my.name=prod环境的name
- application-test.properties
my.name=test环境的name
2.2:数据源切换程序
public class MyCustomPropertyConfig extends PropertyPlaceholderConfigurer {
// 用户配置的所有配置文件对应的资源对象
@Nullable
private Resource[] locations;
// org.springframework.util.PropertiesPersister
// 从不同的数据源读取数据加载到Properties辅助工具类
private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
@Nullable
private String fileEncoding;
@Nullable
public String getFileEncoding() {
return fileEncoding;
}
@Override
public void setFileEncoding(@Nullable String fileEncoding) {
this.fileEncoding = fileEncoding;
}
@Nullable
public Resource[] getLocations() {
return locations;
}
@Override
public void setLocations(@Nullable Resource[] locations) {
this.locations = locations;
}
/**
* spring加载使用的配置信息的方法
*
* @param props 接收用户配置数据的对象
* @throws IOException
*/
@Override
protected void loadProperties(Properties props) throws IOException {
if (props != null) {
// 循环遍历所有的的用户配置文件,根据环境配置找到对应的配置文件并加载到props中
for (Resource location : locations) {
try {
// 处理乱码问题
EncodedResource encodedResource = new EncodedResource(location, this.fileEncoding);
// 当前配置文件的文件名称
String filename = encodedResource.getResource().getFilename();
// 通过环境配置生成最终需要使用的文件名
String env = "application-" + System.getProperty("spring.profiles.active") + ".properties";
// 如果是需要的配置文件,包含即可
if (filename.contains(env)) {
System.out.println("Load property from file " + filename);
// 加载文件内容到props中
try (Reader inputStream = encodedResource.getReader()) {
propertiesPersister.load(props, inputStream);
}
}
} catch (Exception e) {
System.out.println("Load property error, error info is: " + e);
}
}
}
}
}
2.3:测试的bean
public class MyCustomPropertyConfigBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
2.4:xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="yudaosourcecode.multisourcetest.MyCustomPropertyConfig"
id="myCustomPropertyConfig">
<property name="fileEncoding" value="GBK"/>
<property name="locations">
<list>
<value>classpath:multisourcetest/application-dev.properties</value>
<value>classpath:multisourcetest/application-prod.properties</value>
<value>classpath:multisourcetest/application-test.properties</value>
</list>
</property>
</bean>
<bean class="yudaosourcecode.multisourcetest.MyCustomPropertyConfigBean" id="myCustomPropertyConfigBean">
<property name="name" value="${my.name}"/>
</bean>
</beans>
2.5:测试代码
@Test
publicvoid multisourcetest() {
ClassPathXmlApplicationContext ac
= new ClassPathXmlApplicationContext("classpath*:multisourcetest/multisourcetest.xml");
System.out.println(ac.getBean("myCustomPropertyConfigBean"));
}
test
环境运行
Load property from file application-test.properties
{"name":"test环境的name"}
Process finished with exit code 0
dev
环境运行
Load property from file application-dev.properties
{"name":"dev环境的name"}
Process finished with exit code 0
prod
环境运行
·
Load property from file application-prod.properties
{"name":"prod环境的name"}
Process finished with exit code 0