https://my.oschina.net/jack230230/blog/57171html
PropertiesConfiguration config = new PropertiesConfiguration("D:/sms.properties"); FileChangedReloadingStrategy strategy =new FileChangedReloadingStrategy(); strategy.setRefreshDelay(1000); config.setReloadingStrategy(strategy); config.addConfigurationListener(new ConfigurationListener() { @Override public void configurationChanged(ConfigurationEvent event) { if(!event.isBeforeUpdate()){ String changeInfo = "config modify:isBeforeUpdate:"+event.isBeforeUpdate()+",propertyName:"+event.getPropertyName()+",propertyValue:"+ event.getPropertyValue()+",type:"+event.getType()+",source:"+event.getSource(); System.out.println(">>"+changeInfo); } } }); for(;true;){ Thread.sleep(1000); //只有在调用了config.getXXX()方法以后才会进行文件是否修改判断,即修改懒加载 System.out.println(config.getString("sms.statusPull")); }
//只有在调用了config.getXXX()方法以后才会进行文件是否修改判断,即修改懒加载java
你会了解到数据库
从XML文件中获取数据apache
访问环境变量数组
链接不一样类型的配置信息(基于XML的,基于环境变量的,等等)数据结构
在程序改变后自动从新加载配置。app
在咱们的示例中将会使用XML文件和环境变量的两种方式存储一个数据库的配置信息(开发、测试、产品,等等)。接下来你将会看到具体的内容,可是首先先配置一下Maven。框架
Maven设置maven
咱们的示例程序须要在pom.xml文件中添加以下依赖:ide
<dependencies> <dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.8.0</version> </dependency> <dependency> <groupId>commons-jxpath</groupId> <artifactId>commons-jxpath</artifactId> <version>1.3</version> </dependency> </dependencies>
简单的数据库配置
设想咱们有一个简单的数据库配置信息存储在XML文件中:
<?xmlversion="1.0"encoding="UTF-8"?> <!-- const.xml --> <config> <database> <url>127.0.0.1</url> <port>1521</port> <login>admin</login> <password>pass</password> </database> </config>
为了拿到url和port咱们用以下的代码:
XMLConfiguration config =new XMLConfiguration("const.xml"); // 127.0.0.1 config.getString("database.url"); // 1521 config.getString("database.port");
XMLConfiguration是一个Apache Commons类,他能够从指定的配置文件中加载内容,而且提供一个很好的以指定的点的方式获得存储的值。例如例子中的表达式database.port映射到xml文件中的 config/database/port节点的值“1521”。固然还有不少方式获取数据。这里有一些基本的用法:
getBoolean getByte getDouble getFloat getInt getInteger getList getLong getStringArray
你可经过查看Apache Commons的JavaDoc查看更多的使用方式。
将如上配置扩展一步
设想,过了一会咱们想配置多个数据库,咱们能够在配置文件中这样写:
<?xmlversion="1.0"encoding="UTF-8"?> <!-- const.xml --> <config> <databases> <database> <name>dev</name> <url>127.0.0.1</url> <port>1521</port> <login>admin</login> <password>pass</password> </database> <database> <name>production</name> <url>192.23.44.100</url> <port>1521</port> <login>admin</login> <password>not-so-easy-pass</password> </database> </databases> </config>
如今咱们要访问url数据咱们能够这样:
XMLConfiguration config =new XMLConfiguration("const.xml"); // 127.0.0.1 config.getString("databases.database(0).url"); // 192.23.44.100 config.getString("databases.database(1).url");
你能够看到此次多了参数,0表明第一个,1表明第二个。
XPath表达式
定点的访问方式没问题,可是只是在一些简单的状况下,对于复杂的真实的情况来说,咱们可能须要使用XPath表达式语言。这里的主要优势是,即使你使用了XML的高级查询,程序看起来仍然比较简洁易懂。
XMLConfiguration config =new XMLConfiguration("const.xml"); config.setExpressionEngine(new XPathExpressionEngine()); // 127.0.0.1 config.getString("databases/database[name = 'dev']/url"); // 192.23.44.100 config.getString("databases/database[name = 'production']/url");
这里是上面两个XPath表达式查询的一个解释:
访问环境变量
在Apache Commons Configuration的帮助下你能够轻松的访问到系统的环境变量。下面是访问系统中ENV_TYPE变量的方法:
EnvironmentConfiguration config =new EnvironmentConfiguration(); config.getString("ENV_TYPE");
假设变量ENV_TYPE已经设置好了,想看上面的程序是否运行正确,你能够在控制台运行以下脚本:
echo %ENV_TYPE% # for Windows # or... echo $ENV_TYPE # for Linux/Mac OS
你将会看到ENV_TYPE的值。
联合配置
让咱们总结一下咱们了解的东西,下面的getDbUrl方法作以下事情:
public String getDbUrl() throws ConfigurationException { EnvironmentConfiguration envConfig =new EnvironmentConfiguration(); String env = envConfig.getString("ENV_TYPE"); if("dev".equals(env) ||"production".equals(env)) { XMLConfiguration xmlConfig =new XMLConfiguration("const.xml"); xmlConfig.setExpressionEngine(new XPathExpressionEngine()); String xpath ="databases/database[name = '"+ env +"']/url"; return xmlConfig.getString(xpath); }else{ String msg ="ENV_TYPE environment variable is "+ "not properly set"; throw new IllegalStateException(msg); } }
集中你的配置
对每一个不一样的须要配置的对象建立多个配置比较烦。假如咱们想添加其余的基于XML的配置,咱们会怎么搞?咱们须要建立另外一个XMLConfiguration对象,这会给管理带来不少麻烦。一个解决办法是把配置文件信息集中到一个单个XML文件中。下面是一个例子:
<?xmlversion="1.0"encoding="UTF-8"?> <!-- config.xml --> <configuration> <env/> <xmlfileName="const.xml"/> </configuration>
你须要使用DefaultConfigurationBuilder类,最终版本的getDbUrl方法看起来像这样:
public String getDbUrl()throws ConfigurationException { DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder("config.xml"); boolean load =true; CombinedConfiguration config = builder.getConfiguration(load); config.setExpressionEngine(new XPathExpressionEngine()); String env = config.getString("ENV_TYPE"); if("dev".equals(env) ||"production".equals(env)) { String xpath ="databases/database[name = '"+ env +"']/url"; return config.getString(xpath); }else{ String msg ="ENV_TYPE environment variable is "+ "not properly set"; throw new IllegalStateException(msg); } }
自动从新加载
Apache Commons Configuration有不少很是酷的特性。其中一个就是当基于文件的配置变化的时候自动加载,由于咱们能够设置加载策略。框架会轮询配置文件,当文件的内容发生改变时,配置对象也会刷新。你能够用程序控制:
XMLConfiguration config =new XMLConfiguration("const.xml"); ReloadingStrategy strategy =new FileChangedReloadingStrategy(); strategy.setRefreshDelay(5000); config.setReloadingStrategy(strategy);
或者把他写到主配置文件中:
<?xmlversion="1.0"encoding="UTF-8"?> <!-- config.xml --> <configuration> <env/> <xmlfileName="const.xml"> <reloadingStrategyrefreshDelay="5000" config-class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"/> </xml> </configuration>
每五秒框架都检查一下配置文件有没有改变。
最后
我我的用来管理须要配置的代码的时候的选择是使用Apache Commons。我但愿这篇文章可让你相信这个框架能够提供一个很是有用的接口用来访问你的静态数据。最后须要说的一点,这篇文章的内容只是这个框架的功能的一部分。此框架一些其余的有趣的功能是:
http://wangxin0072000.iteye.com/blog/186009
Apache Commons-configuration 学习笔记
1 若是要使用configuration这个包,首先要保证使用JDK1.2以上,还要引入以下jar包
commons-beanutils commons-lang commons-logging commons-collections commons-digester commons-codec commons-jxpath
2 commons-configuration最新的版本是1.5,最主要的做用是读取资源文件,每一种文件格式都有一个对应的类,以下
3 上面已经对它作了基本的介绍,下面看看这个包怎么用吧 好比咱们要读一个properties文件:在classpath下面创建目录te,以后在te下面创建
test.properties
ip=127.0.0.1 port=8080 id=111 application.name = Killer App application.version = 1.6.2 application.title = ${application.name} ${application.version} keys=cn,com,org,uk,edu,jp,hk
java: //注意路径默认指向的是classpath的根目录
Configuration config = new PropertiesConfiguration("te/test.properties"); String ip=config.getString("ip"); int port=config.getInt("port"); String title=config.getString("application.title");
//再举个Configuration的比较实用的方法吧,在读取配置文件的时候有可能这个键值对应的值为空,那么在下面这个方法中
//你就能够为它设置默认值。好比下面这个例子就会在test.properties这个文件中找id的值,若是找不到就会给id设置值为123
//这样就保证了java的包装类不会返回空值。虽然功能很简单,可是很方便很实用。
Integer id=config.getInteger("id", new Integer(123));
//若是在properties 文件中有以下属性keys=cn,com,org,uk,edu,jp,hk
//能够实用下面的方式读取:
String[] keys1=config.getStringArray("keys"); List keys2=config.getList("keys");
首先要把这个文件读到程序中,咱们能够用上面的类,全部的读取文件的类都 继承自AbstractConfiguration类,
而这个类实现了Configuration接口,若是咱们只有比较简单的需求,那么能够直接向上转型为Configuration类型,若是向上
转型为AbstractConfiguration类,那么能够作一些配置工做。
好比刚刚看到的 keys=cn,com,org,uk,edu,jp,hk这个例子中若是是keys=cn/com/org/uk/edu/jp/hk
那么若是还按照原来的方式读取,读到的将是"cn/com/org/uk/edu/jp/hk"这个字符串,因此要先改变分割符以后在读
即
AbstractConfiguration.setDefaultListDelimiter('/'); Configuration config = new PropertiesConfiguration("te/Vasp.properties"); String[] keys=config.getStringArray("keys"); List key2=config.getList("keys");
若是你看它的源码,你会在 AbstractConfiguration这个类中找到:
private static char defaultListDelimiter = ',';
这下你明白了吧!
http://www.360doc.com/content/11/0406/16/2749105_107609102.shtml
Apache Commons Configuration 包使用
Configuration 的参数可能来自下面的资源: * Properties files * XML documents * Property list files (.plist) * JNDI * JDBC Datasource * System properties * Applet parameters * Servlet parameters 不一样的配置资源可以通用 ConfigurationFactory 和 CompositeConfiguration 来混合。
其余的资源能够经过自定义 configuration 对象也可以被建立,这个自定义的对象经过继承 AbstractConfiguration 或者 AbstractFileConfiguration 来实现。
使用 Configuration
配置资源:
如下是常见的配置资源
**混合各类配置资源 **
常常你但愿提供一套基本的配置信息,并且容许用户很容易的根据他们的特有的环境覆盖他们。
一种办法就是载你的代码中队默认值进行硬编码,而且提供一个配置文件来覆盖他们。 这是作法没有一点弹性。替换作法是:运用 CompositeConfiguration 。
CompositeConfiguration config = new CompositeConfiguration(); config.addConfiguration(new SystemConfiguration()); config.addConfiguration(new PropertiesConfiguration("application.properties"));
或者经过ConfigurationFactory这个类
ConfigurationFactory factory = new ConfigurationFactory("config.xml"); Configuration config = factory.getConfiguration();
上面的config.xml是一个配置描述符。它定义了将要被装载的配置对象(资源文件),例如:
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <system/> <properties fileName="application.properties"/> </configuration>
上面的意思是,咱们加载了系统的配置,也加载了application.properties这个文件。 他的优先(precedence)顺序是从前到后。因此在上面的例子中,若是一个属性在系统配置中没有,他将在文件配置中查找 这将容许你在文件配置中设定默认值,并且能够在系统配置中覆盖他们。
Configuration 接口
表明不一样类型配置资源的在这个package中的不一样类共享一个简单的接口:Configuration。 这个接口容许你经过一个基本的方式来访问和处理配置属性。
在Configuration这个接口中的大部分方法用来处理得到的属性的数据类型。这些 方法把一个指向属性的key做为他的入参。他经过查找这个key,得到属性的值,并把它 转化为目标类型。全部的这些方法都有重载方法,能够在没有找到属性时返回一个默认值。 支持的数据类型以下:
这些方法都以get开头,后面是数据的类型。getString()将返回String类型, getInt()将返回int类型。
属性能够有多个值,因此也必须有返回多个值得方法。 getList() 方法能够作到这个。
为了处理属性或者他们的值,下面的方法将会提供帮助:
如下的章节将分别介绍各类不一样的配置资源.
Properties files ( 属性文件 )
属性文件是一种最为流行的配置应用的手段。理所固然, Commons Configuration 支持这种资源格式,而且极大地增强了 java.util.Properties
这个类。这个部分将对 PropertiesConfiguration 做介绍。PropertiesConfiguration是Configuration接口的典型实现,并且在这部分介绍的不少功能
都被其余的各类实现所支持。这是由于他们都继承自AbstractConfiguration。这些功能在AbstractConfiguration中 已经实现。
使用PropertiesConfiguration
咱们有个usergui.properties 的配置文件,内容为:
# Properties definining the GUI colors.background = #FFFFFF colors.foreground = #000080 window.width = 500 window.height = 300
加载这个文件的方法:
Configuration config = new PropertiesConfiguration("usergui.properties"); //文件名
若是你没有定义绝对路径,文件将按一下的路径顺序被查找:
除了能够像上面那样在构造函数中传入一个文件名称来读取外,咱们还能够调用他的 load()方法来读取。
有不少重载的变量提供来装载不一样的资源。更多的内容将在File-based Configurations章节介绍。
在配置文件装载之后,你能够访问各类属性了:
String backColor = config.getString("colors.background"); Dimension size = new Dimension(config.getInt("window.width"), config.getInt("window.height"));
Includes (文件包含)
若是一个属性以include为key,并且它的值是一个磁盘文件。这个文件将会被同时加载。
# usergui.properties include = colors.properties include = sizes.properties ------ # colors.properties colors.background = #FFFFFF Lists and arrays
Commons Configuration 能够很容易的返回一个list类型的值,好比,你的文件中有个用都好分开的多个值。
chart colors
colors.pie = #FF0000, #00FF00, #0000FF
你不须要本身去切割字符串。你能够用下面的方法来返回一个java.util.List或者一个数组:
String[] colors = config.getStringArray("colors.pie"); List colorList = config.getList("colors.pie");
另外一种解决方案是:你能够像下面这样定义成多行。
chart colors
colors.pie = #FF0000; colors.pie = #00FF00; colors.pie = #0000FF;
addProperty() 方法和setProperty() 方法也实现了对list处理。向他们里面传入的值能够是一个list也能够是一个数组。若是传入的属性是一个字符串,他将会检查字符串中是否存在咱们所定义的list分隔符。若是出现这种状况,字符串将会被切割,并且它的各个值将会被分别 当成属性值添加进来。默认的分割符是逗号。他也能够在文件被加载的时候指定。
经过setListDelimiter()方法,你就能够指定分割符。下面是个使用的例子:
// Change the list delimiter character to a slash config.setListDelimiter('/'); //设置分割字符串 // Now add some properties config.addProperty("greeting", "Hello, how are you?"); config.addProperty("colors.pie", new String[] { "#FF0000", "#00FF00", "#0000FF" });//添加时候分割字符串起做用 config.addProperty("colors.graph", "#808080/#00FFCC/#6422FF"); // Access data String salut = config.getString("greeting"); List colPie = config.getList("colors.pie"); String[] colGraph = config.getStringArray("colors.graph"); String firstPieColor = config.getString("colors.pie");
在上面的例子中,分割符由逗号变成了斜线。
或许你会对最后一行有兴趣。这里,getString() 方法被做用在一个多值属性上,这个调用将返回这个list的第一个值。
若是你想对全部的配置对象(资源)设定分割符,你能够用AbstractConfiguration的静态方法setDefaultListDelimiter()来设定。
若是你想让某个配置对象的分隔符不起做用,你能够调用setDelimiterParsingDisabled() 方法,并向他传递true这个参数。
Note:这种list处理和字符串分割机制并非PropertiesConfiguration所特有的, 其余的配置类也具备这种机制。
Variable Interpolation (变量篡改)
若是你对ant或者maven很熟悉的话,你或许多相似${token}这样的变量很熟悉。Commons Configuration也支持这样的
方式。例如:
application.name = Killer App application.version = 1.6.2 application.title = ${application.name} ${application.version}
若是你要返回application.title这个属性的值,将会获得Killer App 1.6.2.和list处理同样,变量篡改的机制也被其余配置类所支持。
Saving ( 存储 )
你能够调用save()来保存你的设置:
PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties"); config.setProperty("colors.background", "#000000); config.save(); //保存文件
你也能够把配置拷贝为另外一个文件
PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties"); config.setProperty("colors.background", "#000000); config.save("usergui.backup.properties);//保存到另外一个文件
更多的关于保存文件的信息请参看“File-based Configurations”的章节。
Special Characters(特殊字符)
若是在你的配置文件中须要用到特殊字符,你能够采用Java字符串相同的转义字符,如: key = This \n string \t contains , escaped \ characters \u0020
**Using a Configuration Factory (使用配置工厂) **
这部分介绍了如何利用ConfigurationFactory对象来访问多个不一样的配置资源。
The configuration definition file(配置定义文件)
当咱们只用一个配置文件的时候,咱们能够采用对应的配置对象,好比PropertiesConfiguration于配置文件或者 XMLConfiguration于xml文件。
可是,接下来咱们将要考虑多个配置资源的状况,咱们须要用ConfigurationFactory来组合他们 ,ConfigurationFactory能够组合多个配置资源。而后咱们就能够像访问单个资源文件同样来访问他们中的属性。首先,咱们须要建立一个 xml文件来告诉工厂哪些文件将要被加载。下面是一个例:
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="usergui.properties"/> </configuration>
ConfigurationFactory的定义文件是一个普通的xml文件.根元素是configuration.他饱含的子元素制定了须要装载的配置 资源.properties是元素之一,他用来包含属性文件.
在上面的例子中,咱们在属性文件相同的目录下定义了一个ConfigurationFactory的配置文件,并命名为config.xml.
Setting up a ConfigurationFactory 如今咱们建立一个ConfigurationFactory并让他来读取定义文件。很简单:得到一个实例,而且在 setConfigurationFileName()中传入定义文件便可。
ConfigurationFactory factory = new ConfigurationFactory();//初始化 URL configURL = new File("config.xml").toURL(); factory.setConfigurationFileName(configURL.toString()); Configuration config = factory.getConfiguration();
在上面的片段里面,咱们向工厂里面穿入了一个娃正德URL.这也是咱们所推荐的指定文件的方式。
由于这种方式提供了最有弹性的和一致的方式来处理在定义文件中的各个相关的文件。
这里咱们假设配置定义文件在当前文件夹下。咱们也能够加载在classpath中的文件。好比:
ConfigurationFactory factory = new ConfigurationFactory(); //初始化 URL configURL = getClass().getResource("/config.xml"); factory.setConfigurationURL(configURL); Configuration config = factory.getConfiguration();
Accessing properties(访问属性)
无论咱们采用什么样的方式来装在配置工厂,咱们最终须要调用工厂的getConfiguration()方法来返回一个配置对象.
这个实例事实上是一个CompositeConfiguration类,一个特殊的Configuration实现--能够用来包含多个配置对象.
理所固然,这个类有Configuration接口提供全部的getter方法,因此咱们得到一个字符串对象仍然是以下的形势:
String backColor = config.getString("color.background");
**Multiple configuration sources(多配置资源) **
用ConfigurationFactory来处理单一资源没有什么意义.因此下面咱们将要迁入一个xml文件. Overriding properties(覆盖属性)
不少应用采用通用的xml格式来做为配置资源.咱们先来个简单的:
<?xml version="1.0" encoding="ISO-8859-1" ?> <gui-definition> <colors> <background>#808080</background> <text>#000000</text> <header>#008000</header> <link normal="#000080" visited="#800080"/> </colors> <rowsPerPage>15</rowsPerPage> </gui-definition>
而后,咱们的配置定义文件须要作以下的修改:
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="usergui.properties"/> <xml fileName="gui.xml"/> </configuration>
创建配置工厂的方法保持不变.新加入的属性能够按通用的方式来访问.
然而,郁闷的事情来了.在2个配置资源中都定义了同一个属性,并且他们又不一样的值.怎么处理? 其实配置资源是从上倒下,从先导后被查找的.若是在前面的配置文件中找到,他就会当即被返回. 彷佛在不一样的资源中配置相同的属性没有意思.可是请考虑如下的场景: (彷佛在前面的介绍中介绍过,笔者再也不翻译).
Optional configuration sources(可选配置文件)
例如:
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="usersettings.properties" optional="true"/> <properties fileName="default.properties"/> </configuration>
上面的例子中,usersettings.properties被定一位一个可选的配置文件.意思是说.若是他没有被加载
ConfigurationFactory并不会跑出异常.可是会写入一段警告信息到日至中.注意:
第二个文件中没有使用optional属性.因此它是被强制的,于是若是他不存在时候,ConfigurationFactory的 getConfiguration()方法会跑出异常.
Union configuration(合并配置) 略
Configuration definition file reference(定义文件) 好比:
<?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <system/> <jndi prefix="java:comp/env"/> <properties fileName="test.properties"/> <xml fileName="test.xml"/> <properties fileName="test.properties.xml"/> </configuration>
另外, AbstractConfiguration还支持注册监听器来监视配置资源的变化.因为时间和篇幅的限制,
XMLConfiguration //apache 处理xml 配置文件的类
PropertiesConfiguration //apache 处理 properties 配置文件的类