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
配置资源:
以下是常见的配置资源
# PropertiesConfiguration
从一个
property
文件中加载配置
.
# XMLConfiguration
从
XML
文件中加载配置信息
.
# PropertyListConfiguration
从一个
.plist
文件中加载配置信息
. XMLPropertyListConfiguration
也可以读取
XML
被
Mac OSX
使用变量
.
# JNDIConfiguration
利用
jndi
树的一个键值,可以返回一个值,这个值来作为配置信息
# BaseConfiguration
访问内存中的一个配置对象
.
# HierarchicalConfiguration
一个在内存中的配置对象,这个对象可以处理复杂的数据结构
.
# SystemConfiguration
一个利用系统属性的配置信息
# ConfigurationConverter
把
java.util.Properties
或者
org.apache.collections.commons.ExtendedProperties
转化为一个
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,获得属性的值,并把它
转化为目标类型。所有的这些方法都有重载方法,可以在没有找到属性时返回一个默认值。
支持的数据类型如下:
·
BigDecimal
·
BigInteger
·
boolean
·
byte
·
double
·
float
·
int
·
long
·
short
·
String
这些方法都以get开头,后面是数据的类型。getString()将返回String类型, getInt()将返回int类型。
属性可以有多个值,所以也必须有返回多个值得方法。
getList()
方法可以做到这个。
为了处理属性或者他们的值,下面的方法将会提供帮助:
addProperty() 添加一个新的属性到配置.如果这个属性已经存在,那么这个属性将变成一个多值属性,并且在多值中增加一个新的.
clearProperty() 从配置中移除特定的属性.
setProperty() 覆写特定的属性
clear() 擦除所有的属性.
以下的章节将分别介绍各种不同的配置资源.
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");
如果你没有定义绝对路径,文件将按一下的路径顺序被查找:
·
in the current directory
当前文件夹
·
in the user home directory
用户根文件夹
·
in the classpath
类路径
除了可以像上面那样在构造函数中传入一个文件名称来读取外,我们还可以调用他的
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还支持注册监听器来监视配置资源的变化.由于时间和篇幅的限制,
笔者不再一一翻译.用户可以参照官方文档