UCM——统一配置文件管理

一个项目中,通常会包含许多参数,这些参数经常会根据运行的环境不同而进行相应的修改。为了修改方便,有时会将这些参数提取出来,放到专门的文件里(通常都是放到扩展名为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托管的beanxml文件中,即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);
}
 
}


然后在springxml文件中添加如下配置项:

<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()了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值