java:学习commons-configuration2读取配置文件xml,properties

commons-configuration是apache为java应用程序提供的一个通用的配置文件管理接口,可以支持多种配置文件格式:

Properties files XML documents Windows INI files Property list files (plist) JNDI JDBC Datasource System properties Applet parameters Servlet parameters

commons-configuration2是在已经广泛使用的commons-configuration 1.x版本基础上的一个升级版本,与1.x版本并不保持兼容。

刚开始使用commons-configuration2,这里做为笔记记录学习过程中的要点。

maven dependency

pom.xml 依赖配置如下,commons-beanutils,commons-jxpath对于commons-configuration2都是optional可选配件,但在本例都要用到所以必须加上否则运行会抛出异常 java.lang.ClassNotFoundException:

        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-configuration2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-configuration2</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-jxpath/commons-jxpath -->
        <dependency>
            <groupId>commons-jxpath</groupId>
            <artifactId>commons-jxpath</artifactId>
            <version>1.3</version>
        </dependency>

xml 表达式引擎

相比properties文件格式 xml要复杂多了(每个节点都可以有attribute),所以对于xml格式的配置文件,访问一个元素的值或attribute需要一套表达式规则来规定。比如路径节点用.分隔,attribute用@开头。commons-configuration提供了默认规则,但这个规则用户也是可以自定义的,也可以使用xpath标准。 下面的代码演示如何使用默认规则、xpath、自定义规则来访问Xml配置文件中的节点. 先贴出演示用的xml文件。 token.xml,放在源码根目录下,是一个很简单的配置文件,其中的description是节点属性。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <token>
        <device>
            <validate>true</validate>
        </device>
        <person>
            <validate>true</validate>
            <expire description="人员令牌失效时间(分钟) ">60</expire>
        </person>
    </token>
</configuration>

ConfigTest2.java

package net.gdface.facelog;

import org.apache.commons.configuration2.XMLConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.tree.DefaultExpressionEngine;
import org.apache.commons.configuration2.tree.DefaultExpressionEngineSymbols;
import org.apache.commons.configuration2.tree.xpath.XPathExpressionEngine;
import org.junit.Test;

public class ConfigTest2 {

    @Test
    public void test2() {
        try {
            Configurations configs = new Configurations();
            XMLConfiguration config = configs.xml(this.getClass().getClassLoader().getResource("token.xml"));
            {
                // 使用默认的符号定义创建一个表达式引擎
                DefaultExpressionEngine engine = new DefaultExpressionEngine(
                        DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS);
                // 指定表达式引擎
                config.setExpressionEngine(engine);
                System.out.println(config.getBoolean("token.device.validate"));
                System.out.println(config.getInt("token.person.expire"));
                System.out.println(config.getString("token.person.expire[@description]"));
            }
            {               
                // 使用 XPath表达式引擎
                // 请注意这里路径分隔符和attribute标签与上面使用DefaultExpressionEngine是不同的
                XPathExpressionEngine xpathEngine = new XPathExpressionEngine();
                config.setExpressionEngine(xpathEngine);
                System.out.println(config.getBoolean("token/device/validate"));
                System.out.println(config.getInt("token/person/expire"));
                System.out.println(config.getString("token/person/expire/@description"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

自定义表达式引擎

如果上面两种表达式引擎都不合你的意,比如不喜欢/@description[@description]这样的attribute标签(我就不喜欢)。你可以用自定义的符号规则生成一个DefaultExpressionEngine表达式引擎对象。 下面的演示就是如何用@做attribute的标签。 这部分的代码来自commons-configuration官网《Expression_engines》

    @Test
    public void test() {
        try
        {
            DefaultExpressionEngineSymbols symbols =
                    new DefaultExpressionEngineSymbols.Builder(
                        DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS)
                        // 指定属性分隔符或可以用xpath的概念叫路径分隔符
                        .setPropertyDelimiter(".")
                        // Indices should be specified in curly brackets
                        .setIndexStart("{")
                        .setIndexEnd("}")
                        // 指定@开头就是attribute标志
                        .setAttributeStart("@")
                        // attribute结尾符为null
                        .setAttributeEnd(null)
                        // A Backslash is used for escaping property delimiters
                        .setEscapedDelimiter("\\/")
                        .create();
            // 用自定义的符号DefaultExpressionEngineSymbols对象创建一个表达式引擎
            DefaultExpressionEngine engine = new DefaultExpressionEngine(symbols);
            Parameters params = new Parameters();
            FileBasedConfigurationBuilder<XMLConfiguration> builder =
                new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
                .configure(params.xml()
                    .setFileName("token.xml")
                    // 使用自定义的表达式引擎
                    .setExpressionEngine(engine));
            XMLConfiguration config = builder.getConfiguration();
            Configurations configs = new Configurations();
            XMLConfiguration config2 = configs.xml(this.getClass().getClassLoader().getResource("token.xml"));
            config2.setExpressionEngine(engine);
            System.out.println(config.getBoolean("token.device.validate"));
            System.out.println(config.getInt("token.person.expire"));
            System.out.println(config.getProperty("token.person.expire@description"));
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
    }

properties文件编码

从properties中读取配置,如果不指定编码类型,是无法正常读取中文内容的。commons-configuration中通过FileBasedConfigurationBuilder.setDefaultEncoding方法来解决这个问题。示例如下:

    @Test
    public void test3(){
        try
        {
            Configurations configs = new Configurations();
            // setDefaultEncoding是个静态方法,用于设置指定类型(class)所有对象的编码方式。
            // 本例中是PropertiesConfiguration,要在PropertiesConfiguration实例创建之前调用。
            FileBasedConfigurationBuilder.setDefaultEncoding(PropertiesConfiguration.class, "UTF-8");
            PropertiesConfiguration propConfig = configs.properties(this.getClass().getClassLoader().getResource("log4j.properties"));
            System.out.println(propConfig.getString("log4j.appender.CONSOLE.Target"));
            System.out.println(propConfig.getBoolean("log4j.appender.LOGFILE.Append"));
            System.out.println(propConfig.getString("test"));
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }

配置文件中使用变量

commons-configuration是允许使用变量的.比如

java.home = ${env:JAVA_HOME} application.name = Killer App application.version = 1.6.2 application.title = ${application.name} ${application.version}

关于这部分的介绍看原文最好:《Variable_Interpolation》

多级配置文件

相当多的应用场景中,一些配置都有默认参数,同时又允许用户修改这些默认参数 ,所以一般会把包含默认参数的配置文件打在jar包中。而允许用户在外部用额外的用户配置文件(比如在user.home文件夹下放用户自定义配置文件)来覆盖默认参数,这就是Overriding properties。 当然用户也可以不提供这个自定义配置文件,全部使用默认参数,也就是说这个自定义配置文件是可选的,这就是Optional configuration sources。 下面的例子就应用了commons-configuration的这两个特性。 先定义一个root.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <properties fileName="${sys:user.home}/.facelog/config.properties" config-optional="true"/>
    <xml fileName="defaultConfig.xml" />
</configuration>

你可以把它当做一个配置文件的控制文件,它用来定义不同级别配置文件的优先级顺序,越往上面文件优先级越高可以覆盖下面文件中定义的变量。所以在最下面的就是默认配置文件,这就实现了Overriding properties。另外,除了最下面的默认配置文件外,上面的文件定义中都有指定config-optional="true"它的意思就是这个文件是可选的,如果该文件不存在也不会报错抛出异常。 在定义配置文件位置时用到的${sys:user.home}就是上一节提到的在配置文件中使用环境变量,${sys:user.home}指定使用JVM系统属性”user.home”(Linux下就是$HOME,Windows下就是%USERPROFILE%)来指定文件位置. 有了这个root.xml,就可以用Configurations.combined方法生成一个CombinedConfiguration对象,在${sys:user.home}下的config.properties定义的属性会覆盖defaultConfig.xml中的值。 调用方法如下

    @Test
    public void test4(){
        try
        {
            DefaultExpressionEngine engine = new DefaultExpressionEngine(DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS);
            Configurations configs = new Configurations();
            // 创建CombinedConfiguration 实例
            CombinedConfiguration config = configs.combined(this.getClass().getClassLoader().getResource("root.xml"));
            config.setExpressionEngine(engine);
            System.out.println(config.getBoolean("token.device.validate"));
            System.out.println(config.getInt("token.person.expire"));
            System.out.println(config.getString("token.person.expire[@description]"));

        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

c#实现打印功能

2602
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4788
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3035
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2496
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

3945
来自专栏C#

DotNet加密方式解析--非对称加密

    新年新气象,也希望新年可以挣大钱。不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬。(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...)...

4788
来自专栏ASP.NETCore

ASP.NET Core 整合Autofac和Castle实现自动AOP拦截

除了ASP.NETCore自带的IOC容器外,我们还可以使用其他成熟的DI框架,如Autofac,StructureMap等(笔者只用过Unity,Ninjec...

674
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2605
来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

1940
来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

5276

扫码关注云+社区