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
这种方式和第一种方式类似,唯一的区别是所有配置会被加载到名为propertiesFactoryBean的bean里,这样我们就可以在别的地方引用它,因此推荐这种方式。
然后是配置文件的读取
配置文件的读取主要针对两种情况,一是在spring“内部”,二是在spring“外部”,下面分别介绍。
在spring托管的bean或xml文件中,即spring“内部”,可以使用${:}的方式,注意里面有个冒号,也就是说我们可以指定一个默认值,当引用的配置项不存在时,spring会使用默认值来填充对应的属性。
1.例如配置一个dataSource:
这里面使用配置时直接${}的方式进行了引用。
2.在代码中引用时,可以使用@Value标签:
注意红色部分,第一个引用了一个配置项,同时当不存在引用的配置项时,对应的值就会填充冒号后面的默认值,即空字符串。
第二个引用项会引用对应的配置并转换为整型并注入到字段中。
还有就是如果目标属性是一个数组,spring会自动把配置项split成数组并注入到字段中(默认是按逗号分隔的,如需使用其他分隔符请自行百度)。
在来说说spring“外部”的情况,在有些时候,代码的上下文是出于非spring托管的,例如早期的定时任务quartz,就是出于spring外部的,这样就无法通过${:}的方式直接获取了配置了,此时我们可以通过使用一些静态类来把所有的配置“引出”来,这样就能解决我们的问题。
编写如下类(请无视类的名字,因为此类还有其他用途,这里不做介绍):
然后在spring的xml文件中添加如下配置项:
注意红色字体部分,这里引用了前面定义的一个bean。同时注意下,这个bean的创建方式使用了factory-method="getInstance"方法。
这样我们就可以在任何地方SpringContextHolder.getInstance().getProperty()了。
在一个项目中,通常会有若干个配置文件,例如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()了。
相关文章推荐
- Web前沿—HTML5 Form Data 对象的使用
- Jtopo 拓扑图
- 第8周项目3-指向学生类的指针
- nodejs 同步创建文件夹
- Css边框
- [文档] TDDL和Diamond的使用(一):基本介绍
- iOS极光推送之自定义消息
- 配置你喜欢的 IDE
- 一些有价值的网页链接整理
- Spring基础之 BeanFactory与FactoryBean
- BZOJ_1497_[NOI2006]_最大获利_(最大流+最大权闭合图)
- 举例讲解Java的Spring框架中AOP程序设计方式的使用
- 使用正则表达式找出不包含特定字符串的条目
- HTTP网络连接相关知识整理(六):分发处理根异常
- android inflater 用法
- nodejs koa forEach 不能使用 yield
- Java基础知识IO流(字节流的缓存区并自定义)
- java 日期格式转换EEE MMM dd HH:mm:ss z yyyy
- POJ1331 Multiply(strtol函数练习)
- redis web manager