您的位置:首页 > 其它

UCM——统一配置文件管理

2016-04-27 16:35 218 查看
一个项目中,通常会包含许多参数,这些参数经常会根据运行的环境不同而进行相应的修改。为了修改方便,有时会将这些参数提取出来,放到专门的文件里(通常都是放到扩展名为properties的文件里),这种文件称作配置文件(属性文件)。
在一个项目中,通常会有若干个配置文件,例如jdbc.properties经常用来存放数据库连接信息;log4j.properties经常用来存放log4j的配置等。

UCM,既统一配置文件管理,也就是所有配置文件统一加载、统一读取。
UCM通常考虑如下几个问题:
配置文件的存放
配置文件可以是存在于任何地方的properties文件,例如存在于项目的WEB-INF/classes路径,或者某个jar中,又或者磁盘的其他位置,同时支持通配符,这样就能实现批量加载功能。
配置文件的加载
加载的方式可以为由spring统一加载,或者自己编码去读取等。
配置文件的读取
配置文件的读取主要针对两种情况,一是在托管“内部”,二是在托管“外部”。
配置属性的添加和获取采用“匿名”的方式
既配置文件加载方不知道都有哪些配置属性,只有配置文件“供应方”和“使用方”知道需要哪些属性
支持属性的重载
即当存在多个同名的配置项时,后者会覆盖前者。
 
下面以spring为例,介绍UCM的一种实现思路。
首先是配置文件的加载
这里让spring去加载所有的配置文件。spring自身对properties的加载支持的非常好,这里例举推荐的两种加载方式:
1.使用context:property-placeholder标签
<context:property-placeholderlocation="classpath:/config/jdbc.properties" ignore-resource-not-found="true"ignore-unresolvable="true"/>
<context:property-placeholderlocation="file:/d:/simon.properties"ignore-resource-not-found="true"ignore-unresolvable="true"/>
这里加载了两个配置文件,第一个位于项目的classpath下,另一个位于磁盘的d:/simon.properties。且如果两个配置文件中有相同的配置的话,后者会覆盖前者。
注意,尽量配置上ignore-resource-not-found="true"ignore-unresolvable="true"这两个属性,可以避免很多问题。
2.使用PropertiesFactoryBean

<beanid="propertiesFactoryBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean"  lazy-init="false">
<property name="ignoreResourceNotFound"value="true" />
<property name="locations">
<list>
<value>classpath:/config/jdbc.properties</value>
<value>classpath:/config/*.properties</value>
<value>file:/d:/simon.properties</value>
</list>
</property>
</bean>

这种方式和第一种方式类似,唯一的区别是所有配置会被加载到名为propertiesFactoryBean的bean里,这样我们就可以在别的地方引用它,因此推荐这种方式。
然后是配置文件的读取
配置文件的读取主要针对两种情况,一是在spring“内部”,二是在spring“外部”,下面分别介绍。
在spring托管的bean或xml文件中,即spring“内部”,可以使用${:}的方式,注意里面有个冒号,也就是说我们可以指定一个默认值,当引用的配置项不存在时,spring会使用默认值来填充对应的属性。

1.例如配置一个dataSource:

<bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName"value="${jdbc.driverClass}"></property>
<property name="url"value="${jdbc.jdbcUrl}"></property>
<property name="username"value="${jdbc.username}"></property>
<property name="password"value="${jdbc.password}"></property>
</bean>


这里面使用配置时直接${}的方式进行了引用。

2.在代码中引用时,可以使用@Value标签:
 

public class SessionInterceptor {

@Value("${web.sessionfilter.excludedUrls:}")
private String indexUrl = null;

@Value("${web.login.allowchangeip:1}")
private Integer allowChangeIp ;
………………

注意红色部分,第一个引用了一个配置项,同时当不存在引用的配置项时,对应的值就会填充冒号后面的默认值,即空字符串。
第二个引用项会引用对应的配置并转换为整型并注入到字段中。
还有就是如果目标属性是一个数组,spring会自动把配置项split成数组并注入到字段中(默认是按逗号分隔的,如需使用其他分隔符请自行百度)。
 
在来说说spring“外部”的情况,在有些时候,代码的上下文是出于非spring托管的,例如早期的定时任务quartz,就是出于spring外部的,这样就无法通过${:}的方式直接获取了配置了,此时我们可以通过使用一些静态类来把所有的配置“引出”来,这样就能解决我们的问题。
编写如下类(请无视类的名字,因为此类还有其他用途,这里不做介绍):

public class SpringContextHolderextends PreferencesPlaceholderConfigurer {

private static ApplicationContext applicationContext;

private static SpringContextHolder instance = null;

private static Properties props;

public static SpringContextHolder getInstance(){
if(instance==null){
instance=new SpringContextHolder();
}
return instance;
}

/*
* @authorShixy
*@date   2016年1月4日
* @seeorg.springframework.beans.factory.config.PropertyPlaceholderConfigurer#processProperties(org.springframework.beans.factory.config.ConfigurableListableBeanFactory,java.util.Properties)
*/
@Override
protected voidprocessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,Properties props) throws BeansException {
super.processProperties(beanFactoryToProcess, props);
SpringContextHolder.props = props;
}

public static String getProperty(String key) {
return props.getProperty(key);
}

public static String getProperty(String key, StringdefaultValue) {
return props.getProperty(key, defaultValue);
}

}


然后在spring的xml文件中添加如下配置项:

<beanclass="com.stanley.framework.utils.SpringContextHolder"  factory-method="getInstance"lazy-init="false">
<property name="properties" ref="propertiesFactoryBean" />
</bean>

注意红色字体部分,这里引用了前面定义的一个bean。同时注意下,这个bean的创建方式使用了factory-method="getInstance"方法。
这样我们就可以在任何地方SpringContextHolder.getInstance().getProperty()了。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UCM