Commons Configuration之二基本特性和AbstractConfiguration

Configuration接口定义一大堆方法。一切从头开始实现这些方法非常困难。因为AbstractConfiguration类存在。该类在Commons Configuration中充当大多数Configuration实现的共同基类并提供了接口需要的大量功能。因此创建一个自定义Configuration实现该类将是一个很好的起点。
除了基本实现声明在Configuration接口中的方法之外,AbstractConfiguration类提供一些其它的便利特性。因为该类是在Commons Configuration类层次结构的根,这些特性对该类库提供的Configuration接口的大多数特定实现都是有效的。

1    处理缺失属性

如果你传入一个键给它的get方法之一,不能映射到一个已存在的属性,配置对象该做什么?AbstractConfiguration实现的默认行为是如果返回值是对象类型返回null。对于原始类型作为返回null(或任意特定值)是不可能的,因此,在这种情况下一个NoSuchElementException抛出:

// 如果没有键为"NonExistingProperty"的属性将返回null
String strValue = config.getString("NonExistingProperty");

// 如果没有键为"NonExistingProperty"的属性将抛出一个NoSuchElementException异常
long longValue = config.getLong("NonExistingProperty");

对于对象类型,像String、BigDecimal或BigInteger这种默认行为可以改变:如果setThrowExceptionOnMissing()方法使用一个true参数调用,这些方法将像原始类型一样,如果传入的属性键不能解析抛出一个异常。

注意:不幸的是支持throwExceptionOnMisssing属性不总是一致:getList()和getStringArray()不计算该标记,如果请求属性没有找到返回一个空list或数组。也许这种行为将在未来的重要版本改变。

2    List处理

使用Configuration接口定义的getList()和getStringArray()方法处理多值属性。当一个配置源(例如properties文件、XML文档或JNDI上下文)处理相应Configuration实现发现这么一个有多个值的属性并确保该数据正确存储。

当修改属性时,AbstractConfiguration的addProperty()和setProperty()方法也实现特定list处理。传入这些方法的属性值可以是list或数组产生一个多值属性。如果属性值是字符串,它检测是否字符串包含list分隔符。如果是这种情况,字符串被分割,并且它单个部分被添加。list分隔符默认是逗号。当配置源被加载时,它在考虑之内(例如,属性的字符串值将被检测是否包含分隔符)。通过使用setListDelimiter()方法你能设置它为一个不同的字符。

// 改变list分隔符为斜线
config.setListDelimiter(‘/‘);
// 现在添加一些属性
config.addProperty("greeting", "Hello, how are you?");
config.addProperty("colors.pie", new String[] { "#FF0000", "#00FF00", "#0000FF" });
config.addProperty("colors.graph", "#808080/#00FFCC/#6422FF");

// 访问数据
String salut = config.getString("greeting");
List<Object> colPie = config.getList("colors.pie");
String[] colGraph = config.getStringArray("colors.graph");

String firstPieColor = config.getString("colors.pie");

在该例子中,list分隔符从逗号变为斜线。因为greeting属性没有分割,而是保存为单个字符串。作为字符串传入的colors.graph属性相反包含新的分隔符因此产生一个三个值的属性。注意,list是Object类型。这是因为不知道属性值的具体类型。例如,如果你调用addProperty("answer", 42),一个Integer对象将存储在配置中。

感兴趣的是例子片段的最后一行。调用的getString()方法有多个值。这将返回list的第一个值。

如果你想要改变所有配置对象的list分隔符,你可以使用AbstractConfiguration的静态setDefaultListDelimiter()方法。也可以通过调用使用true的setDelimiterParsingDisabled()方法禁用所有的Configuration实例的字符串属性的切分。

3    变量插值

如果你熟悉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}。prefix告诉Commons Configuration变量在某一上下文中计算。我们可以看到,如果prefix缺失,上下文是当前配置实例。以下是默认支持的prefix名称。

前缀 描述
sys 该前缀标记一个变量是系统属性。Commons Configuration将使用指定名称搜索一个系统属性并通过该值替换变量。这非常容易的在每个配置实现中访问系统属性的值。
const const前缀表示一个变量解释为一个类的常量成员字段(例如,使用static final修饰符的字段)。变量的名字必须是<完全限定类名>.<字段名>的形式。指定类将被加载并且该字段的值将被获取。
env 变量也能引用特定OS环境变量。这通过evn前缀表示。

下面是一些例子,只针对Properties文件:

PropertiesConfiguration cfg = new PropertiesConfiguration("cfg/basic/vm.properties");
System.out.println(cfg.getString("vm.name"));
System.out.println(cfg.getString("vm.author"));
System.out.println(cfg.getString("vm.home"));
System.out.println(cfg.getString("vm.bin"));

public interface Const {

public static final String AUTHOR = "Evan";
    
}

#相当于System.getProperty("java.runtime.name")

vm.name=${sys:java.runtime.name}
vm.author=${const:cfg.basic.Const.AUTHOR}

#相当于System.getEnv("JAVA_HOME")

vm.home=${env:JAVA_HOME}
vm.bin=${vm.home}\bin

如果一个变量不能解析,例如,因为名称无效或未知前缀,它不能被替换,但返回包括美元符号和大括号。

3    自定义插值

本节阐述你如何添加自己的插值。使用Commons Lang的text包下的StrSubstitutor类实现插值引擎。该类使用派生自StrLookup类的对象解析变量。StrLookup定义简单lookup()方法必须通过自定义实现;它期望变量名作为参数并返回相应的值(更多细节可以在Commons Lang的文档中找到)。我们已经介绍了标准的前缀变量,到目前为止我们确实已经实现派生自StrLookup的特定类。

现在可以创建你自己的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调用变量。为了这个目的EchoLookup类必须在ConfigurationInterpolator类使用期望前缀注册。 ConfigurationInterpolator在Commons Lang定义的StrLookup API中实现一个简单的包装器。它有一个静态registerGlobalLookup()方法,我们必须如下调用:

// 放置该代码在你的应用程序初始化的地方
ConfigurationInterpolator.registerGlobalLookup("echo", new EchoLookup());

每个在该行代码之后创建的AbstractConfiguration对象将包含新的查询类并能因此解析${echo:my_variable}形式的变量。

每个AbstractConfiguration实例关联一个ConfigurationInterpolator对象。该对象在第一次访问插值特性之一时通过createInterpolator()方法创建。通过覆盖该方法可能更深入的干预插值机制。例如自定义实现能添加更高级的查询对象到插入器。

4    使用表达式(此处没有明白如何使用,请高人指点一二)

除了前面描述的简单的查找机制,Commons Configuration提供ExprLookup,使用Apache Commons Jexl允许表达式解析是否一个StrLookup被允许。如果ExprLookup被配置,该例子显示显示获取系统属性的替代方式。

user.file = ${expr:System.getProperty("user.home"}/settings.xml

ExprLookup默认被禁用,必须通过DefaultConfigurationBuilder手动添加或配置。使用Maven 2构建并引用Commons Configuration将不包括Jexl依赖,因此如果该特性被使用必须手动添加依赖到项目。

使用DefaultConfigurationBuilder添加ExprLookup是直接的。

<configuration>
  <header>
    <result/>
    <lookups>
      <lookup config-prefix="expr"
              config-class="org.apache.commons.configuration.interpol.ExprLookup">
        <variables>
          <variable name="System" value="Class:java.lang.System"/>
          <variable name"net" value="Class:java.net.InetAddress"/>
          <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
        </variables>
      </lookup>
    </lookups>
  </header>
  <override>
    <xml fileName="${expr:System.getProperty(‘basePath‘) +
         String.lowercase(net.localHost.hostName) + ‘/testMultiConfiguration_default.xml‘}"
         config-name="defaultConfig" delimiterParsingDisabled="true">
    </xml>
  </override>
</configuration>

上面的例子显示如何在表达式计算期间调用静态方法。下一个例子显示使用下级查询混合表达式计算获取“basePath”系统属性。注意获取系统属性和之前例子的差异。

<configuration>
  <header>
    <result/>
    <lookups>
      <lookup config-prefix="expr"
              config-class="org.apache.commons.configuration.interpol.ExprLookup">
        <variables>
          <variable name"net" value="Class:java.net.InetAddress"/>
          <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
        </variables>
      </lookup>
    </lookups>
  </header>
  <override>
    <xml fileName="${expr:$[sys:basePath] +
         String.lowercase(net.localHost.hostName) + ‘/testMultiConfiguration_default.xml‘}"
         config-name="defaultConfig" delimiterParsingDisabled="true">
    </xml>
  </override>
</configuration>

时间: 2024-10-13 10:58:14

Commons Configuration之二基本特性和AbstractConfiguration的相关文章

Apache Commons Configuration之三Properties文件

Properties文件是流行的应用程序配置文件.当然,Commons Configuration支持这种格式并显著增强了基础的java.util.Properties类.本文介绍PropertiesConfiguration类的特性.注意PropertiesConfiguration是实现Configuration接口非常典型的例子,本文描述许多特性(例如,list处理或插值)其它配置类也支持.这是因为Commons Configuration附带的大多数配置实现派生自实现这些特性的共同基类A

Apache Commons Configuration之一简介

1    简介 Commons Configuration软件类库提供通用配置接口,使Java应用程序从多种源读取配置文件.Commons Configuration提供简单类型访问和通过以下代码演示的多义配置参数: Double double = config.getDouble("number"); Integer integer = config.getInteger("number"); 配置参数可以从以下源加载: Properties文件 XML文档 Pr

使用Apache Commons Configuration读取配置信息

在项目中使用一些比较新的库总会给你带来很多快乐,在这篇文章中,我将会给你介绍一个在Java中读取配置文件的框架--Apache Commons Configuration framework. 你会了解到 ·从XML文件中获取数据 ·访问环境变量 ·连接不同类型的配置信息(基于XML的,基于环境变量的,等等) ·在程序改变后自动重新加载配置. 在我们的示例中将会使用XML文件和环境变量的两种方式存储一个数据库的配置信息(开发.测试.产品,等等).接下来你将会看到具体的内容,但是首先先配置一下Ma

commons configuration的简单使用和说明

Commons Configuration是一个java应用程序的配置管理工具.可以从properties或者xml文件中加载软件的配置信息,用来构建支撑软件运行的基础环境.在一些配置文件较多较的复杂的情况下,使用该配置工具比较可以简化配置文件的解析和管理.也提高了开发效率和软件的可维护性. 官方主页:[url]http://commons.apache.org/configuration/[/url] 1 如果要使用configuration这个包,首先要保证使用JDK1.2以上,还要引入如下

Attribute(二)——自定义特性+Asp.net MVC中的filter详解

上篇博客是关于特性中有关预定义特性的一些基础,同时也是对Attribute这一概念的一个宏观上的认识,在上篇博客结尾介绍了有关为自定义特性服务的AttributeUsage,这篇博客主要是通过filter的使用间接的了解自定义特性的具体应用. 一.filter简介 在了解自定义特性前,先引入一个概念filter,它是MVC中自带的一种功能,在我们项目中通常会遇到在Action执行前或结束时,去执行日志记录或错误处理等功能,通常可使用AOP截取来实现,但是在MVC中提供了filter过滤,大大方便

PHP语言的十二种特性

命名约定前后矛盾.版本兼容相互冲突,PHP语言在各个层面上都给开发人员带来了诡异而难解的谜局--这就是我们今天要讨论的话题.我们真的对PHP深恶痛绝吗?不,当然不是.如果真是这样,我们就不会如此广泛地使用Drupal.WordPress以及其它一些同类框架.假设我们真的讨厌PHP,那么最直接的办法是转向Java而非在这里放什么厥词.不过需要提醒各位拥护者的是,也别因为熟悉而对PHP的那些缺陷视而不见. 转换令人头痛 在利用PHP进行项目创建的过程中,最大的挑战之一在于牢记我们哪些时候需要输入HT

Spring Cloud Commons教程(二)Spring RestTemplate作为负载平衡器客户端

RestTemplate可以自动配置为使用功能区.要创建负载平衡RestTemplate创建RestTemplate @Bean并使用@LoadBalanced限定符. 警告 通过自动配置不再创建RestTemplate bean.它必须由单个应用程序创建. @Configuration public class MyConfiguration { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(

二 面向对象三大特性

一 继承与派生 一.继承定义 二.继承与抽象的关系 三.继承与重用性 四.派生 五.组合与重用性 六.接口与归一化设计 七.抽象类 八.继承实现的原理 九.子类中调用父类的方法 二 多态与多态性 一.多态 二.多态性 三 封装 一.封装定义 二.特性(property) 三.封装与扩展性 一 继承与派生 一.继承定义 什么是继承 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类. 子类会“”遗传”父类的属性,从而

Apache Commons 工具集

一.Commons BeanUtils http://jakarta.apache.org/commons/beanutils/index.html 说明:针对Bean的一个工具集.由于Bean往往是有一堆get和set组成,所以BeanUtils也是在此基础上进行一些包装. 使用示例:功能有很多,网站上有详细介绍.一个比较常用的功能是Bean Copy,也就是copy bean的属性.如果做分层架构开发的话就会用到,比如从PO(Persistent Object)拷贝数据到VO(Value O