NCNC

WTGGT,TTGG

张忠良ID:sunjavaduke
90614次访问,排名948好友0人,关注者2
优于别人,并不高贵,真正的高贵是优于昨天的自己
这个世界上最伟大的事情并不是已经取得的成就,而是前进的方向
sunjavaduke的文章
原创 9 篇
翻译 39 篇
转载 1 篇
评论 0 篇
sunjavaduke的公告
Contact me
最近评论
文章分类
收藏
    相册
    vic
    Favorite
    ASF
    存档
    订阅我的博客
    XML聚合  FeedSky

    翻译 Apache Commons Configuration Part1收藏

    新一篇: Hibernate Study Part1 Introduction | 旧一篇: Unknown Source in Log4j

    本文是Apache官方网站的Apache Commons件中的Configuration的翻译的第一部分。主要参考了Apache官方网站的介,用指南以及Javadocs。如有转载声明!
    Commons Configuration提供了一个通用的配置接口,允Java用程序从各种源文件中取配置数据,它提供了访问单值和多配置参数的典型方式,如下面代所示:
    Double double = config.getDouble("number");
    Integer integer = config.getInteger("number");
    配置参数可以从以下源中加载:
               属性文件Properties files
               XML文档XML documents
               Windows INI文件Windows INI files
               属性列表文件Property list files (plist)
               JNDI服务器JNDI
               JDBC数据源JDBC Datasource
               系统属性System properties
               Applet参数Applet parameters
               Servlet参数Servlet parameters
    不同的配置源可以通过使用ConfigurationFactoryCompositeConfiguration进行结合使用,可以通过使用自定义的配置对象来创建配置参数的附件的源文件。可以通过继承AbstractConfiguration类或者AbstractFileConfiguration类来进行配置源的自定义。更多详细的内容,参考javadoc文档。
    用户指南
    注:用户指南中描述的很多功能是在版本1.3中新追加的,如果使用的版本是1.2的话,可以参考后面以前的Howtos文档。
    1.配置的使用
    可以通过使用Commons Configuration来存取各种资源中的配置属性,这些配置属性可以存储在属性文件,xml文档,JNDI树等等,它们都可以通过通用的Configuration接口来进行访问。Commons Configuration的另外一个优势是它可以处理多种配置源,然后再将它们看作是逻辑上单独的配置。本部分内容介绍了不同的配置源以及如何组合它们。
    目前已经存在很多不同的配置源对象。但是,与使用一个特定类型(例如XMLConfigurationJNDIConfiguration)Configuration对象相比,真正获取配置的值的方法对用户是透明的。一下类代表了不同的配置源:
    ·         PropertiesConfiguration从属性文件中加载属性值。
    ·         XMLConfigurationXML文档中获取值。
    ·         INIConfigurationWindows.ini文件中加载值。
    ·         PropertyListConfigurationOpenStep.plist文件中加载值。XMLPropertyListConfiguration类可以在Mac OS系统中读取XML属性。
    ·         JNDIConfiguration使用JNDI树种的键来获取值。
    ·         BaseConfiguration在内存中创建Configuration对象的方法。
    ·         HierarchicalConfiguration内存中的Configuration对象,可以处理复杂结构数据。
    ·         SystemConfiguration系统属性配置。
    ·         ConfigurationConverter使用java.util.Properties或者org.apache.commons.collections.ExtendedProperties,并将它转换成Configuration对象。
    组合配置源:
    一般情况下,需要为用户设置默认的属性值,然后由用户根据特定的环境进行修改并覆盖默认值。一种方式是通过硬编码,在代码中使用默认值,然后提供一个覆盖这个文件的属性文件。但是,这种实现方式有些欠缺灵活性。取而代之的是,使用CompositeConfiguration来提供建立配置的多种实现方式。实现方式1是通过手工创建:
    CompositeConfiguration config = new CompositeConfiguration();
    config.addConfiguration(new SystemConfiguration());
    config.addConfiguration(new PropertiesConfiguration("application.properties"));
    还可以通过工厂类创建:
    ConfigurationFactory factory = new ConfigurationFactory("config.xml");
    Configuration config = factory.getConfiguration();
    这里的config.xml文件是一个配置描述符,它指定了要加载的Configuration。下面是一个示例:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <configuration>
     <system/>
     <properties fileName="application.properties"/>
    </configuration>
    上面的配置描述符表示加载了所有的系统属性和application.properties中的属性。属性的先后顺序是从前到后。所以,在上面的例子中,如果一个属性在系统属性中没有发现,那么将在属性文件中进行查找。这种方式可以在属性文件中设置默认值,然后再系统属性中进行覆盖。
    Configuration接口:
    所有这个包中用于表示不同类型配置源的类都实现了同一个接口:Configuration。可以通过这个通用的接口存取和操作配置属性。
    Configuration接口中定义的大多数方法都用于获取不同数据类型的属性。所有这些方法都使用key作为参数。key是一个字符串值,具体的含义取决于具体的Configuration实现。通过key查找属性,然后将它转换为目标类型,并将转换后的值返回。并且这些方法都包含一个重载的方法,允许指定一个默认值,如果找不到属性值,就返回默认值。支持一下的数据类型:
    ·         BigDecimal
    ·         BigInteger
    ·         boolean
    ·         byte
    ·         double
    ·         float
    ·         int
    ·         long
    ·         short
    ·         String
    方法名是使用get作为前缀,然后是数据类型。例如getString()方法返回String类型的数据。getInt()方法操作integers
    属性可能存在多个值,所以有可能在列表中查找所有的值,这个功能可以通过getList方法来完成。可以使用下面的方法来操作属性和他们的值。
    addProperty()
    将一个新的属性添加到配置中。如果这个属性已经存在了,那么添加一个另外的值。这样它就会变成一个多值(multi-valued)的属性。
    clearProperty()
    将指定的属性从配置中移除。
    setProperty()
    覆盖制定的属性的值。这和删除属性然后调用addProperty()的效果是一样的。
    clear()
    清除所有的配置。
    线程相关:
    Configuration接口的大多数具体实现都不是线程安全的。他们可以被并行的以read-only方式来访问。如果一个线程修改了configuration对象,那么就需要手工的进行同步,来确保数据的正确。
    线程安全的具体实现在javadoc中已经进行了说明。
    2.基本功能和AbstractConfiguration
    Configuration接口定义了非常多的方法,从头开始实现这些方法是比较困难的,所以定义了一个抽象类AbstractConfiguration。这个类作为很多Configuration借口实现类的基类,并提供了很多接口要求的功能的实现。到目前为止,创建一个自定义的Configuration实现,只需要继承AbstractConfiguration类。
    AbstractConfiguration类除了提供了一些方法的基本实现外,还提供了一些其他的实用的方法。因为这个类是Commons Configuration层次中的根级别的类。这些功能在很多子类中都可以使用。本部分内容将会涉及一些基本的功能。
    处理遗漏的属性:
    如果传递的key没有对应的属性的话,那么configuration该如何处理呢?在AbstractConfiguration中默认返回null(如果返回值的类型是Object类型)。如果返回值是原始类型,那么没有办法返回null。所以就会抛出NoSuchElementException
    // This will probably return null
    String strValue = config.getString("NonExistingProperty");
    // This might throw an exception
    long longValue = config.getLong("NonExistingProperty");
    对于类似StringBigDecimal或者BigInteger这样的对象类型,可以修改默认的功能:如果使用true作为参数调用setThrowExceptionOnMissing()方法,这些方法就会和原始类型一样跑出异常。
    注:但是,throwExceptionOnMissing属性并不总是有效,getList()getStringArray()方法不检查这个标志,而是返回空的列表或者数组。
    处理列表:
    Configuration接口定义了用于处理具有多个值得属性的方法getList()getStringArray()。当配置源(例如属性文件,XML文档或者JNDI上下文)被处理时,相应的Configuration实现回哦检查是否有多个值,以便确保数据可以被正确的保存。
    AbstractConfiguration类中定义了addPropertysetProperty方法来修改属性,同时也实现了特定的列表的处理。传递到这些方法中的属性值可以是一个列表和数组,表示一个属性具有多个值。如果属性值是一个字符串,就会检查是否包含列表分隔符字符。如果包含了分隔符,就会将字符串进行分割,每个单独的部分都一个一个的添加。默认情况下,列表的分隔符是逗号。经常会在加载的时候进行这样的检查(例如属性的字符串数值是否包含分隔符)。通过使用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");
    在这个例子中,列表的分隔符并不是逗号,而是斜线。所以greeting属性不会被分割,而是作为一个字符串。而colors.graph属性包含了自定义的分隔符,所以会返回一个包含三个值的属性。
    最有意思的是上述代码片断的最后一行,getString()方法用来调用包含多值得属性,这时会返回多个属性值列表的第一个。
    如果需要修改列表的分隔符,可以使用AbstractConfiguration的静态的setDefaultListDelimiter()方法。可以通过调用setDelimiterParsingDisabled()方法来禁止使用分割字符串。此时的参数为true
    插入变量:
    用过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。所以每个默认的变量都被转换成了其他键的属性值。这只是一个特例,通用的变量名的语法为${prefix:name}。前缀用于提示Commons Configuration变量是在指定的上下文中被处理。如果没有prefix的话,那么就使用当前的configuration。下面是默认情况下支持的前缀:
    sys        系统属性
    const    const前缀表示变量值可以被一个类的常量的值进行替换。也就是说static final修饰的变量。变量名必须是<full qualified class name>.<field name>。指定的类会被加载,然后获取常量的值。
    下面是两个示例:
    user.file = ${sys:user.home}/settings.xml
    action.key = ${const:java.awt.event.KeyEvent.VK_CANCEL}
    如果变量不能被处理的话,例如名称是不合法的,或者前缀不合法,那么它就不会被替换,返回值就是${xxx}
    自定义插入:
    本部分内容涉及到插入的后台处理,并介绍了自定义插入的一些方法。插入方法是用了Commons Langtext包下的StrSubstitutor类。这个类使用StrLookup类的对象来处理变量。StrLookup类定义了一个简单的lookup方法,这个方法必须由自定义实现类实现。它以便两名作为参数,并返回对应的值。细节请参考Commons Lang的文档。标准的前缀是通过StrLookup的具体实现来完成的。
    可以通过继承StrLookup类,并实现lookup方法来自定义插入。
    import org.apache.commons.lang.text.StrLookup;
    public class EchoLookup extends StrLookup
    {
        public String lookup(String varName)
        {
            return "Value of variable " + varName;
        }
    }
    现在希望将用这个类处理echo为前缀的变量。就需要将这个类使用ConfigurationInterpolator类进行注册。
    // Place this code somewhere in an initialization section of your application
    ConfigurationInterpolator.registerGlobalLookup("echo", new EchoLookup());
    每个AbstractConfiguration的实例都和一个ConfigurationInterpolator对象关联。
    3.属性文件
    属性文件是非常流行的应用程序配置方式。所以Commons Configuration自然会支持这种格式的配置,并对java.util.Properties类进行了增强。本部分内容介绍了PropertiesConfiguration类的功能。PropertiesConfiguration是非常典型的Configuration接口的实现类,同时这个类中的多数功能都被其他的Configuration类支持。这是由于大多数配置实现都继承自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”);
    如果没有置顶绝对路径,那么将在如下的路径进行自动搜索:
               当前路径
               用户主目录
               类路径
    也可以不使用构造器来创建PropertiesConfiguration对象,而是使用load方法。有很多重载的load方法,包含了不同的参数,支持不同的源。
    属性文件被加载后,就可以访问它的内容了。
    String backColor = config.getString("colors.background");
    Dimension size = new Dimension(config.getInt("window.width"),
    config.getInt("window.height"));
    包含关系
    如果有一个名为include的属性,而它的值就是磁盘上的一个文件,那么这个文件会被加载到configuration中,例如:
    # usergui.properties
    include = colors.properties
    include = sizes.properties
     
    # colors.properties
    colors.background = #FFFFFF
    列表和数组
    正如之前提到的一样,Commons Configuration可以返回一个属性的多个值,以数组或者列表的形式。例如,一个属性文件可以包含一系列都好分割的值:
    # chart colors
    colors.pie = #FF0000, #00FF00, #0000FF
    不需要对值进行分割就可以获取一个数组或者java.util.List对象:
    String[] colors = config.getStringArray("colors.pie");
    List colorList = config.getList("colors.pie");
    当然,也可以使同一个key在多行上出现多次:
    # chart colors
    colors.pie = #FF0000;
    colors.pie = #00FF00;
    colors.pie = #0000FF;
    所有在上一节中讨论的关于列表处理的功能都是用于属性文件。包括改变分隔符和禁用列表处理。
    保存
    当需要保存配置时,只需要调用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);
    特殊字符
    如果需要在属性文件中使用特殊的字符,例如tab键、unicode字符,可以通过相同的转义字符进行转义。列表的分隔符也可以被转义。
    key = This \n string \t contains \, escaped \\ characters \u0020
    布局对象
    每个PropertiesConfiguration对象都与一个Layout对象相关联,即PropertiesConfigurationLayout得实例。这个对象负责保存加载的配置文件的结构,也就是说,注释或者空行与以前的文件一样。
    正常情况下,开发人员不需要处理这些布局对象。但是有些方法是很有用的,例如PropertiesConfigurationLayout实例定义了用于获取和设置注释的方法。同时还支持对整个属性文件的注释。如果一个多值属性必须放在一行的话,(这样可以与java.util.Properties兼容),可以调用setForceSingleLine()方法。
     

    发表于 @ 2008年04月05日 21:53:00|编辑

    评论:没有评论。

    Csdn Blog version 3.1a
    Copyright © sunjavaduke