?Configuration
簡介
?
Configuration
的參數(shù)可能來自下面的資源:
??? *? Properties files
??? * XML documents
??? * Property list files (.plist)
??? * JNDI
??? * JDBC Datasource
??? * System properties
??? * Applet parameters
??? * Servlet parameters
不同的配置資源能夠通用
ConfigurationFactory
和
CompositeConfiguration
來混合。
其他的資源可以通過自定義
configuration
對象也能夠被創(chuàng)建,這個自定義的對象通過繼承
AbstractConfiguration
或者
AbstractFileConfiguration
來實(shí)現(xiàn)。
使用
Configuration
?
配置資源:
? ?
以下是常見的配置資源
? #? PropertiesConfiguration?
從一個
property
文件中加載配置
.
?# XMLConfiguration
從
XML
文件中加載配置信息
.
?# PropertyListConfiguration
從一個
.plist
文件中加載配置信息
. XMLPropertyListConfiguration
也可以讀取
XML
被
Mac OSX
使用變量
.
?
?# JNDIConfiguration
利用
jndi
樹的一個鍵值,可以返回一個值,這個值來作為配置信息
?# BaseConfiguration
訪問內(nèi)存中的一個配置對象
.
?# HierarchicalConfiguration
一個在內(nèi)存中的配置對象,這個對象可以處理復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
.
?# SystemConfiguration
一個利用系統(tǒng)屬性的配置信息
?# ConfigurationConverter
把
java.util.Properties
或者
? org.apache.collections.commons.ExtendedProperties
轉(zhuǎn)化為一個
Configuration
對象
.
混合各種配置資源
?
經(jīng)常你希望提供一套基本的配置信息,而且允許用戶很容易的根據(jù)他們的特有的環(huán)境覆蓋他們。
????
一種辦法就是載你的代碼中隊(duì)默認(rèn)值進(jìn)行硬編碼,并且提供一個配置文件來覆蓋他們。
?
這是做法沒有一點(diǎn)彈性。替換做法是:運(yùn)用
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>
???
上面的意思是,我們加載了系統(tǒng)的配置,也加載了application.properties這個文件。
他的優(yōu)先(precedence)順序是從前到后。所以在上面的例子中,如果一個屬性在系統(tǒng)配置中沒有,他將在文件配置中查找
。這將允許你在文件配置中設(shè)定默認(rèn)值,而且可以在系統(tǒng)配置中覆蓋他們。
Configuration
接口
?
代表不同類型配置資源的在這個package中的不同類共享一個簡單的接口:Configuration。
這個接口允許你通過一個基本的方式來訪問和處理配置屬性。
? 在Configuration這個接口中的大部分方法用來處理獲得的屬性的數(shù)據(jù)類型。這些
方法把一個指向?qū)傩缘?span lang="EN-US">key作為他的入?yún)ⅰKㄟ^查找這個key,獲得屬性的值,并把它
轉(zhuǎn)化為目標(biāo)類型。所有的這些方法都有重載方法,可以在沒有找到屬性時返回一個默認(rèn)值。
支持的數(shù)據(jù)類型如下:
·????????????
BigDecimal
·????????????
BigInteger
·????????????
boolean
·????????????
byte
·????????????
double
·????????????
float
·????????????
int
·????????????
long
·????????????
short
·????????????
String
?
這些方法都以get開頭,后面是數(shù)據(jù)的類型。getString()將返回String類型, getInt()將返回int類型。
???屬性可以有多個值,所以也必須有返回多個值得方法。
getList()
方法可以做到這個。
???為了處理屬性或者他們的值,下面的方法將會提供幫助:
???addProperty() 添加一個新的屬性到配置.如果這個屬性已經(jīng)存在,那么這個屬性將變成一個多值屬性,并且在多值中增加一個新的.
???clearProperty() 從配置中移除特定的屬性.
???setProperty() 覆寫特定的屬性
???clear() 擦除所有的屬性.
?以下的章節(jié)將分別介紹各種不同的配置資源.
???
Properties files
(
屬性文件
)
???
屬性文件是一種最為流行的配置應(yīng)用的手段。理所當(dāng)然, Commons Configuration 支持這種資源格式,并且極大地加強(qiáng)了
java.util.Properties
這個類。這個部分將對
PropertiesConfiguration
作介紹。PropertiesConfiguration是Configuration接口的典型實(shí)現(xiàn),而且在這部分介紹的很多功能
都被其他的各種實(shí)現(xiàn)所支持。這是因?yàn)樗麄兌祭^承自AbstractConfiguration。這些功能在AbstractConfiguration中已經(jīng)實(shí)現(xiàn)。
???使用PropertiesConfiguration
???我們有個usergui.properties 的配置文件,內(nèi)容為:
# Properties definining the GUI
colors.background = #FFFFFF
colors.foreground = #000080
window.width = 500
window.height = 300
加載這個文件的方法:
Configuration config = new PropertiesConfiguration("usergui.properties");
???
如果你沒有定義絕對路徑,文件將按一下的路徑順序被查找:
·?
in the current directory
當(dāng)前文件夾
·?
in the user home directory
用戶根文件夾
·?
in the classpath?
類路徑
??
除了可以像上面那樣在構(gòu)造函數(shù)中傳入一個文件名稱來讀取外,我們還可以調(diào)用他的
load()
方法來讀取。
有很多重載的變量提供來裝載不同的資源。更多的內(nèi)容將在File-based Configurations章節(jié)介紹。
??在配置文件裝載以后,你可以訪問各種屬性了:
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或者一個數(shù)組:
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() 方法也實(shí)現(xiàn)了對list處理。向他們里面?zhèn)魅氲?span lang="EN-US">
值可以是一個list也可以是一個數(shù)組。如果傳入的屬性是一個字符串,他將會檢查字符串中是否
存在我們所定義的list分隔符。如果出現(xiàn)這種情況,字符串將會被切割,而且它的各個值將會被分別
當(dāng)成屬性值添加進(jìn)來。默認(rèn)的分割符是逗號。他也可以在文件被加載的時候指定。通過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() 方法被作用在一個多值屬性上
,這個調(diào)用將返回這個list的第一個值。
???如果你想對所有的配置對象(資源)設(shè)定分割符,你可以用AbstractConfiguration
的靜態(tài)方法setDefaultListDelimiter()來設(shè)定。如果你想讓某個配置對象的分隔符不起作用
,你可以調(diào)用setDelimiterParsingDisabled() 方法,并向他傳遞true這個參數(shù)。
???Note:這種list處理和字符串分割機(jī)制并不是PropertiesConfiguration所特有的,
其他的配置類也具有這種機(jī)制。
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處理一樣,變量篡改的機(jī)制也被其他配置類所支持。?
???
Saving
(
存儲
)
你可以調(diào)用save()來保存你的設(shè)置:
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);
更多的關(guān)于保存文件的信息請參看“File-based Configurations”的章節(jié)。
Special Characters(特殊字符)
如果在你的配置文件中需要用到特殊字符,你可以采用Java字符串相同的轉(zhuǎn)義字符,如:
key = This \n string \t contains \, escaped \\ characters \u0020
Using a Configuration Factory
(使用配置工廠)
?這部分介紹了如何利用ConfigurationFactory對象來訪問多個不同的配置資源。
?The configuration definition file(配置定義文件)
?當(dāng)我們只用一個配置文件的時候,我們可以采用對應(yīng)的配置對象,比如PropertiesConfiguration于配置文件或者XMLConfiguration于xml文件。
?但是,接下來我們將要考慮多個配置資源的情況,我們需要用ConfigurationFactory來組合他們
?ConfigurationFactory可以組合多個配置資源。然后我們就可以像訪問單個資源文件一樣來訪問他們中的屬性。首先,我們需要創(chuàng)建一個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
?現(xiàn)在我們創(chuàng)建一個ConfigurationFactory并讓他來讀取定義文件。很簡單:獲得一個實(shí)例,并且在setConfigurationFileName()中傳入定義文件即可。
ConfigurationFactory factory = new ConfigurationFactory();
URL configURL = new File("config.xml").toURL();
factory.setConfigurationFileName(configURL.toString());
Configuration config = factory.getConfiguration();
?在上面的片斷里面,我們向工廠里面穿入了一個娃正德URL.這也是我們所推薦的指定文件的方式。
?因?yàn)檫@種方式提供了最有彈性的和一致的方式來處理在定義文件中的各個相關(guān)的文件。
?這里我們假設(shè)配置定義文件在當(dāng)前文件夾下。我們也可以加載在classpath中的文件。比如:
?ConfigurationFactory factory = new ConfigurationFactory();
URL configURL = getClass().getResource("/config.xml");
factory.setConfigurationURL(configURL);
Configuration config = factory.getConfiguration();
Accessing properties(訪問屬性)
? ?不管我們采用什么樣的方式來裝在配置工廠,我們最終需要調(diào)用工廠的getConfiguration()方法來返回一個配置對象.
這個實(shí)例事實(shí)上是一個CompositeConfiguration類,一個特殊的Configuration實(shí)現(xiàn)--可以用來包含多個配置對象.
理所當(dāng)然,這個類有Configuration接口提供所有的getter方法,所以我們獲得一個字符串對象仍然是如下的形勢:
String backColor = config.getString("color.background");
Multiple configuration sources(多配置資源)
?用ConfigurationFactory來處理單一資源沒有什么意義.所以下面我們將要遷入一個xml文件.
?Overriding properties(覆蓋屬性)
? 很多應(yīng)用采用通用的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個配置資源中都定義了同一個屬性,而且他們又不同的值.怎么處理?
?答案是:配置資源是從上倒下,從先導(dǎo)后被查找的.如果在前面的配置文件中找到,他就會立即被返回.
?似乎在不同的資源中配置相同的屬性沒有意思.但是請考慮以下的場景:
?(似乎在前面的介紹中介紹過,筆者不再翻譯).
??
?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屬性.所以它是被強(qiáng)制的,因而如果他不存在時候,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還支持注冊監(jiān)聽器來監(jiān)視配置資源的變化.由于時間和篇幅的限制,
筆者不再一一翻譯.用戶可以參照官方文檔