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 配置文件的類