我们的项目通常会发布在不同的系统、不同的受众环境提供外部或内部访问,如:内测、公测、生产环境、基于 WIN/LINUX等。发布至不同的环境,我们通常会配置不同的数据库账户密码、连接数、生成测试数据等。如果没有一套固定的机制自动配置,而在发布时手工修改,犯错率不仅很大,同时效率也很低。
程序员的优点是懒,缺点是不够懒。O(∩_∩)O哈哈哈~
以下分为 Spring App 和 Spring MVC 两种场景介绍,目的是打包前改一个变量,它能自动读取对应配置。如 env = prod
先创建一个 MyProperties 用于装载属性 key/value:
package com.caobug.demo.springenv;
/**
* 属性
* <p>
* Created by caobug on 16/6/26.
*
* @author caobug
* @since 1.7
*/
public class MyProperties {
private String ipAddress;
private String username;
private String password;
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "MyProperties{" +
"ipAddress='" + ipAddress + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
再创建配置文件spring-config.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">
<beans profile="developer">
<bean id="myProperties" class="com.caobug.demo.springenv.MyProperties">
<property name="username" value="a"/>
<property name="ipAddress" value="192.168.1.2"/>
<property name="password" value="123456"/>
</bean>
</beans>
<beans profile="production">
<bean id="myProperties" class="com.caobug.demo.springenv.MyProperties">
<property name="username" value="b"/>
<property name="ipAddress" value="192.168.1.3"/>
<property name="password" value="654321"/>
</bean>
</beans>
</beans>
以上代码和平时的依赖注入没什么差别,仅仅是多了属性 profile="developer"
,他用于告诉 Spring 这需要特定环境才生效。这里还有一种写法是把以下片段:
<beans xmlns="http://www.springframework.org/schema/beans"
替换为:
<beans profile="developer" xmlns="http://www.springframework.org/schema/beans"
这样做之后将需要创建不同的XML文件,环境一多就不好维护了。
我们用JUNIT验证下我们的做法:
package com.caobug.demo.springenv;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by caobug on 16/6/26.
*
* @author caobug
* @since 1.7
*/
public class MyPropertiesTest {
@Test(expected = NoSuchBeanDefinitionException.class)
public void notFound() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
// ctx.getEnvironment().setActiveProfiles("developer");
// ctx.refresh();
MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
System.out.println("developer myProperties = " + myProperties);
}
@Test
public void developer() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
ctx.getEnvironment().setActiveProfiles("developer");
ctx.refresh();
MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
System.out.println("developer myProperties = " + myProperties);
}
@Test
public void production() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
ctx.getEnvironment().setActiveProfiles("production");
ctx.refresh();
MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
System.out.println("production myProperties = " + myProperties);
}
}
我们需要特别注意的是,如果我们没有为ctx
设定对应的环境(developer or production),或者有设定但未调用ctx.refresh();
时,若尝试获取bean
将会抛出NoSuchBeanDefinitionException
异常,请参考以上notFound()
测试方法。
楼上说:想RUN就RUN!不管了,我们再来看下 Spring MVC 中如何配置: