`
mzhj
  • 浏览: 228078 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Commons-Collections.jar

阅读更多
如果你不熟悉Jakarta Commons话,那么很有可能你已经重新发明了好几个轮子。在你编写更多的普通的框架或工具之前,体验一下Commons吧。它将会大大地节约你的时间。太多的人自己写一个,其实是与Commons Lang中的StringUtils重复的StringUtils类,或者,开发者不知道从Commons Collections中重新创建工具,哪怕commons-collections.jar已经在classpath中可用了。

真的,请停一下。看看Commons Collections API,然后再回到你的任务中;我发誓你会发现一些简单有用的东西可以帮你在明年节省一周的时间。如果大家花一点时间看看Jakarta Commons,我们将会得到更少的重复代码—我们将在重用的宗旨下真正做一些有用的事情。

我确实看到这样的情况发生过:一些人研究了一下Commons BeanUtils或者Commons Collections,然后总是有“啊,如果我那时知道这个的话,我就不会写那一万行的代码了”这样的时刻。Jakarta Commons仍有一部分保持相当的神秘;比如,许多人还没有听说过Commons CLI和Commons Configuration,并且大多数人还没有注意到Commons Collections中的functors(算子)包的价值。在这一系列中,我会专门强调一些Jakarta Commons中较少得到重视的工具和功能。

在这一系列的第一部分,我将探索定义在Commons Digester中的XML规则,Commons Collections中的功能,和使用一个有趣的应用,Commons JXPath,来查询一个对象的List。Jakarta Commons包含的功能目的在于帮助你解决低层次的编程问题:遍历集合,解析XML和从List中检出对象。我建议你花一些时间在这些小功能上,学习Jakarta Commons真的会为你节省不少时间。

并不简单地是学习使用Commons Digester来解析XML或者使用CollectionUtils的Predicate来过滤一个集合,而是当你一旦意识到如何将这些功能组合起来使用并且如何将Commons集成到你的项目中去的时候,你才会真正地看到它的好处。如果你这样做地话,你将会把commons-lang.jar, commons-beanutils.jar,和 commons-digester.jar当成JVM本身来看待。

如果你对Jakarta Commons更深的内容感兴趣的话,可以看一下Jakarta Commons Cookbook。这本书给你很多方法来更好的使用Commons,并告诉你如何将Jakarta Commons与其它的小的开源组件集成,如Velocity, FreeMarker, Lucene, 和 Jakarta Slide。这本书,我介绍了一组广泛的工具从Commons Lang中的简单工具到组合了Commons Digester, Commons Collections, 和Jakarta Lucene来搜索威廉.莎士比亚的著作。我希望这一系列和Jakarta Commons Cookbook这本书能够提供给你一些有趣的低层次的编程问题的解决方案。

1. 用于Commons Digester的基于XML的规则集
Commons Digester 1.6提供了将XML转化为对象的最简单的方法。Digester已经由O'Reilly网站上的两篇文章介绍过了:“学习和使用Jakarta Digester”,作者是Philipp K. Janert,和“使用Jakarta Commons, 第二部分”,作者是Vikram Goyal。两篇文章都演示了XML规则集的使用,但如何在XML中定义规则集并没有理解。大多所见到的Digester的使用是程序化地定义规则集,以已编译的形式。你应该避免硬编码的Digester规则,特别是当你可以将映射信息存储在外部文件中或一个类路径资源中时。外部化一个Digester规则可以更好地适应一个演化中的XML文档结构或者说一个演化中的对象模型。

为了演示在XML中定义规则集与硬编码的规则集之间的区别,考虑系统解析XML给一个Person bean,包括在下面定义的属性—id, name和age。
package org.test;

public class Person {
  public String id;
  public String name;
  public int age;
               
  public Person() {}

  public String getId() { return id; }
  public void setId(String id) {
    this.id = id;
  }

  public String getName() { return name; }
  public void setName(String name) {
    this.name = name;
  }

  public int getAge() { return age; }
  public void setAge(int age) {
    this.age = age;
  }
}
确认你的应用需要解析一个包含了多个person元素的XML文件。下面的XML文件,data.xml,包含了两个person元素,你想要把它们解析到Person对象中:
<people>
  <person id="1">
    <name>Tom Higgins</name>
    <age>25</age>
  </person>
  <person id="2">
    <name>Barney Smith</name>
    <age>75</age>
  </person>
  <person id="3">
    <name>Susan Shields</name>
    <age>53</age>
  </person>
</people>

你希望如果结构和XML文件的内容在未来几个月中变化,你不需要在已编译的Java代码中硬编码XML文件的结构。为了做到这一点,你需要在一个XML文件中定义Digester的规则,并且它可以作为一种资源从类路径中装入。下面的XML文档,person-rules.xml,映射person元素到Person bean:

<digester-rules>
  <pattern value="people/person">
    <object-create-rule classname="org.test.Person"/>
    <set-next-rule methodname="add" paramtype="java.lang.Object"/>
    <set-properties-rule/>
    <bean-property-setter-rule pattern="name"/>
    <bean-property-setter-rule pattern="age"/>
  </pattern>
</digester-rules>

上述所做的是指示Digester创建一个新的Person实例,当它遇到一个person元素时,调用add()来将Person对象加入到一个ArrayList中,设置person元素中相匹配的属性,并从下一级元素name和age中设置name和age的属性。

现在你已经看到了Person类,会被解析的文档,和以XML的形式定义的Digester规则。现在你需要创建一个由person-rules.xml定义了规则的Digester的实例。下面的代码创建 了一个Digester,通过将person-rules.xml的URL传递给DigesterLoader

既然person-rules.xml文件是与解析它的类在同一个包内的类路径资源,URL可以通过getClass().getResource()来得到。DigesterLoader然后解析规则并将它加到新创建的Digester上:

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;

// 从XML规则集中配置Digester
URL rules = getClass().getResource("./person-rules.xml");
Digester digester = DigesterLoader.createDigester(rules);

// 将空的List推入到Digester的堆栈
List people = new ArrayList();
digester.push( people );

// 解析XML文档
InputStream input = new FileInputStream( "data.xml" );
digester.parse( input );

一旦Digester完成对data.xml的解析,三个Person对象将会在ArrayList people中。
与将规则定义在XML不同的方法是使用简便的方法将它们加入到一个Digester实例中。大多数文章和例子都用这种方法,使用addObjectCreate() 和 addBeanPropertySetter()这样的方法来将规则加入中Digester上。下面的代码加入了与定义在person-rules.xml中相同的规则:

digester.addObjectCreate("people/person", Person.class);
digester.addSetNext("people/person", "add", "java.lang.Object");
digester.addBeanPropertySetter("people/person", "name");
digester.addBeanPropertySetter("people/person", "age");

如果你曾经发现自己正在用一个有着2500行代码的类,用SAX来解析一个巨大的XML文档,或者使用DOM或JDOM的完整的一个集合类,你就会理解XML的解析比它应该做的要复杂的多,就大多数情况来说。如果你正在建一个有着严格的速度和内存要求的高效的系统,你会需要SAX解析器的速度。如果你需要DOM级别3的复杂度,你会需要像Apache Xerces的解析器。但如果你只是简单的试图将几个XML文档解析到对象中去的话,看一下Commons Digester, 并把你的规则定义在一个XML文件中。

任何时候你都应该将配置信息从硬编码中移出来。我会建议你在一个XML文件中定义规则并从文件系统或类路径中装入它。这样可以使你的程序更好地适应XML文档以及对象模型的变化。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics