- 浏览: 495332 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (139)
- JAVA (20)
- Database (11)
- Flex (2)
- OXM (1)
- Oracle (17)
- Persistence (2)
- IDE (5)
- Software Development (12)
- Operation System (22)
- Spring (1)
- Computer (3)
- WEB Server (6)
- Industry Applications (11)
- Project Management (1)
- Web Service (1)
- Linux (9)
- HTML (2)
- Crypto (1)
- Lucene (3)
- Hadoop (10)
- Java Script (2)
- Search (7)
- Python (1)
最新评论
-
bcabchappy:
win7下面无效:当前盘符:%~d0原样输出了
CMD获取当前目录的绝对路径 -
gpo:
很好
struts2文件上传如何限制上传文件类型(类型列表) -
zl0828:
很好的东西,顶你,分享
CMD获取当前目录的绝对路径
摘要:Jakarta Commons Digester 学习笔记 |
Digester是Jakarta 子项目Commons下的一个模块,支持基于规则的对任意XML文档的处理。它最初是Structs项目的一部分,后因其通用性而划归Commons. 下载及编译cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
password: anoncvs cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/digester cd jakarta-commons/digester ant dist Digester的运行依赖下列包:
一个简单的例子假定有两个JavaBean如下,分别为Foo和Barpackage mypackage;
public class Foo { public void addBar(Bar bar); public Bar findBar(int id); public Iterator getBars(); public String getName(); public void setName(String name); } public mypackage; public class Bar { public int getId(); public void setId(int id); public String getTitle(); public void setTitle(String title); } 用下面的xml文件进行配置 <foo name="The Parent">
<bar id="123" title="The First Child"/> <bar id="456" title="The Second Child"/> </foo> 用下面几行代码即可完成配置文件解析工作:
基本情况熟悉用SAX来处理XML文档的程序员,会发现Digester隐藏了遍历XML元素这些细节,而是提供了更高一层的、更友好的SAX事件接口,从而让程序员的精力放在对数据的处理过程中。使用Digester,须按照以下步骤:
元素匹配模板Digester能自动遍历目标XML文档的元素形成的层次结构,这个过程无需程序员参与。程序员的任务是决定,在解析的过程中,当由嵌套的元素形成的一个特定序列被识别出时,如何处理它。用以描述这种序列的机制,就叫“元素匹配模板”。具体说来,元素和其子元素间,用”/”相隔,如果一些元素前没有”/”则其必为根元素。如例: <a> -- 匹配模板 "a"
<b> -- 匹配模板 "a/b" <c/> -- 匹配模板 "a/b/c" <c/> -- 匹配模板 "a/b/c" </b> <b> -- 匹配模板 "a/b" <c/> -- 匹配模板 "a/b/c" <c/> -- 匹配模板 "a/b/c" <c/> -- 匹配模板 "a/b/c" </b> </a> 字符”*”表示任意级别,如”*/a”表示任意级别的<a>都可匹配(不包括根元素级的).熟悉XLST的朋友,对这种思路一定不陌生。 从上面的描述,可知某个元素同时满足多个匹配模板是非常可能的,在这种情况下,与各个模板相关联的处理规则(processing rule)的执行顺序如下:对begin或body方法,按照各个rule的注册顺序的先后,对end方法则是注册顺序的反序。 处理规则(processing rule)元素匹配模板用以识别什么时候采取行动,处理规则则用以定义行动的内容。从形式上讲,一个处理规则是一个java类,它扩展了org.apache.commons.digester.Rule类。每个处理规则,实现下列 的一个或几个事件处理方法(event method),当相应的模板匹配成功以后,在已定义的某个时刻,这些事件方法会被触发。
在设置digester时,通过调用addRule()方法,来注册一个特定的元素匹配模板以及相应的一个Rule类的实例。如上所述,Rule类中的事件处理方法,会在适当的时间被调用。这个机制,允许动态地生成Rule的实现。 另外,digester也提供了一些处理常见情况的处理规则类。
对这些标准的规则类,可以创建它们的实例,并调用digester.addRule来注册它们。由于经常使用它们,所以digester定义了一些简便的方法来注册它们。如: Rule rule = new SetNextRule(digester, "addChild","com.mycompany.mypackage.MyChildClass");
可以用下列代码替换
digester.addRule("a/b/c", rule); digester.addSetNext("a/b/c", "addChild", "com.mycompany.mypackage.MyChildClass");
对象栈对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于 XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此 栈的基本操作包括:
用栈的原因,就是当识别出一个XML元素的“开始”时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的“结束”时,则弹出此对象,并进行相关的处理。 如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建 立起一种“父子关系”,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象). 如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。 日志(logging)日志是一个调试Digester规则集的非常重要的工具,它可以记录非常丰富的信息,因它在使用Digester之前有必要了解日志是如何工作的。 Digester使用Jakarta Commons Logging,这个模块并不是具体的日志实现,而只是一个可设置的接口。可以设置它将各种日志信息传递它自身带的基本记录器,或者传递给其它的更复杂的 日志工具。具体请参考commons logging的文档,或Jakarta Commons Logging学习笔记 Digester主要使用两个记录器:
假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester=debug
org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester.sax=info
Digester包中的例子***********Example.xml**********
运行结果如下(运行时可能需要xml-crimson,一个源sun的XML解析器,可到http://xml.apache.org/crimson/下载)
<address-book> <person id="1" category="acquaintance" try="would be ignored"> <name>Gonzo</name> <email type="business">gonzo@muppets.com</email> <gender result="the whole tag would be ignored">male</gender> </person> <person id="2" category="rolemodel"> <name>Kermit</name> <email type="business">kermit@muppets.com</email> <email type="home">kermie@acme.com</email> </person> </address-book>**********Person.java************ import java.util.HashMap; import java.util.Iterator; public class Person { private int id; private String category; private String name; private HashMap emails = new HashMap(); //下面的两个方法的名字中set以后的部分,与<person>的属性名字对映。当从xml文件中识别出<person> 的属性时,如果有要求(即调用过addSetProperties方法),Digester会依据这种对映关系自动调用相应的方法。 public void setId(int id) { this.id = id; } public void setCategory(String category) { this.category = category; } //对name而言,因为其值来自<name>标签的内容而非属性值,需要用addCallMethod指定识别<name>后的要调用此方法(想自动调用也要可以,需要addBeanPropertySetter,参见第下一个例子)。 public void setName(String name) { this.name = name; } //同name,此时还要一一指定addEmail的参数值的来源。 public void addEmail(String type, String address) { emails.put(type, address); } public void print() { System.out.println("Person #" + id); System.out.println(" category=" + category); System.out.println(" name=" + name); for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) { String type = (String) i.next(); String address = (String) emails.get(type); System.out.println(" email (type " + type + ") : " + address); } } } **********AddressBook.java*********** import java.util.LinkedList; import java.util.Iterator; public class AddressBook { LinkedList people = new LinkedList(); public void addPerson(Person p) { people.addLast(p); } public void print() { System.out.println("Address book has " + people.size() + " entries"); for(Iterator i = people.iterator(); i.hasNext(); ) { Person p = (Person) i.next(); p.print(); } } } ************AddressBookDigester********* import org.apache.commons.digester.Digester; /** * Usage: java Example1 example.xml */ public class AddressBookDigester { public static void main(String[] args) { if (args.length != 1) { usage(); System.exit(-1); } String filename = args[0]; // 创建一个Digester实例 Digester d = new Digester(); // 创建AddressBook实例,并将其压入栈顶。 AddressBook book = new AddressBook(); d.push(book); // 增加规则 addRules(d); // 处理输入的xml文件 try { java.io.File srcfile = new java.io.File(filename); d.parse(srcfile); } catch(java.io.IOException ioe) { System.out.println("Error reading input file:" + ioe.getMessage()); System.exit(-1); } catch(org.xml.sax.SAXException se) { System.out.println("Error parsing input file:" + se.getMessage()); System.exit(-1); } // 将解析出的地址数据打印出来 book.print(); } private static void addRules(Digester d) { // 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶 d.addObjectCreate("address-book/person", Person.class); // 将<person>标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根 据各自的名字进行映射,(例如,将标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行 映射),然后将属性的值作参数传递给执行相应的方法。 // 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属性)。 d.addSetProperties("address-book/person"); // 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数 d.addSetNext("address-book/person", "addPerson"); // 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。 // 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数,且参数的值是元素的内容) d.addCallMethod("address-book/person/name", "setName", 0); // 当遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail 方法,addEmail方法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。 // 此处addCallParam方法的第一参数是规则,第二个参数是指明被调用方法(addEmail)参数的序号,第三个是参数为字符串时指属性的名字) d.addCallMethod("address-book/person/email", "addEmail", 2); d.addCallParam("address-book/person/email", 0, "type"); d.addCallParam("address-book/person/email", 1); } private static void usage() { System.out.println("Usage: java Example1 example.xml"); } } Address book has 2 entries
Person #1 category=acquaintance name=Gonzo email (type business) : gonzo@muppets.com Person #2 category=rolemodel name=Kermit email (type business) : kermit@muppets.com email (type home) : kermie@acme.com 配置属性Digester用来解析应用系统的配置文件,其本身也有很可配置的属性。
除了上述属性外,还可以注册一个本地DTD,以供DOCTYPE声明引用。这样的注册告诉XML解析器,当遇到DOCTYPE声明时,应使用刚注册的DTD的内容,而不是DOCTYPE声明中的标识符(identifier)。 例如,Struect框架控制器中,使用下述的注册,告诉Structs使用一个本地的DTD中的相关内容来处理Structs配置文件,这样可以适 用于那些没有连接到互联网的应用环境,而在连到互联网的环境中可以加快运行速度(因为它避免了通过网络去取相关的资源)。 URL url = new URL("/org/apache/struts/resources/struts-config_1_0.dtd");
digester.register("-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",url.toString()); 规则集打包通常情况下,一个规则被创建后,接着便注册,然后等在event时被调用,这些规则集很难为其它应用程序直接复用。一个解决方法是将所有规则都放在一 个类中,此由这些规则可以很简单地被装载然后被注册使用。RuleSet接口就是为些而设计,一般是通过扩展RuleSetBase类来开发规则集类。如 例: public class MyRuleSet extends RuleSetBase {
可以这样使用这个规则集
public MyRuleSet() { this(""); } public MyRuleSet(String prefix) { super(); this.prefix = prefix; this.namespaceURI = "http://www.mycompany.com/MyNamespace"; } protected String prefix = null; public void addRuleInstances(Digester digester) { digester.addObjectCreate(prefix + "foo/bar", "com.mycompany.MyFoo"); digester.addSetProperties(prefix + "foo/bar"); } } Digester digester = new Digester();
... 一些配置Digester ... digester.addRuleSet(new MyRuleSet("baz/")); 带命名空间的XML解析这种情况下,使用Digester的步骤为:
另外,在指明要digester考虑命名空间之后,在定义匹配模板时,可以将命名空间别名加“:”作为元素名称的一部分使用。这与无命名空间时是一致的。 开发定制的匹配处理过程通过实现 org.apache.commons.digester.Rules接口或扩展org.apache.commons.digester.RulesBase类来达到定制匹配过程的目的。 Digester提供ExtendedBaseRules来扩展了匹配模板的定义,引入了特殊通配字符?和*以及!,提供RegexRules来支持 以正则式的语法定义匹配模板,提供WithDefaultsRulesWrapper来支持默认规则(即其它规则都不匹配时的处理规则)。 一些认识通过看说明材料,尤其在学习Digester包中的Catalog例子以后,有一些认识: 1、由于xml对属性名字的定义要求,与Java中对方法名字的定义要求不一致,导致出现不能自动映射的情况,如year-made标签属性,就不可能有方法setYear-made; 2、对于根元素,与其子元素建立联系,有几种办法:一种是先生成根元素实例,压入栈,然后解析,将调用方法规则建立联系;另一种是解析的过程中第一个创建它,然后用getRoot的方法得到。 3、如果某对象类构造都要参数,则此时需要扩展AbstractObjectCreationFactory类为这种对象建立一个Factory,在这个Factory中取得初始化参数值然后再创建一个对象实例。 4、设有某个标签,要想自动用该标签子元素的内容填充该标签对应的对象的属性,则需要用digester.setRules(new ExtendedBaseRules()),然后addRules(),然后再调用addBeanPropertySetter("bala/lala /?");进行规则定义,注意此模板中有通配符。 5、如果对象的属性是整型,则Digester自动将xml文件中字符串值转换为整型。 6、在指明要digester考虑命名空间之后,如果不会引起歧义,完全可以忽略命名空间的存在,除非你要针对特定的命名空间进行特定的处理。
原作者:Hilton |
发表评论
-
Eclipse中集成Tomcat
2016-07-11 21:46 497问题: 很多时候在Eclipse中启动Tmocat后,不能 ... -
DOS运行Java命令的同时添加依赖jar包及参数
2015-08-03 18:58 615方案一: java -classpath %classpat ... -
用myeclipse打jar包,使其包含依赖jar包的指向
2015-08-03 14:21 2013第一步:建目录,将依赖JAR包都拷贝到该目录下,比如我的这个 ... -
IBATIS Error getting ordinal list from JavaBean的特殊问题
2015-01-24 23:12 2281iBatis作为持久层的组件,为广大开发人员提供了极 ... -
GC 日志解读/分析
2014-07-15 18:10 998打印gc log的详细信息 Java代码 ... -
Tomcat下配置BoneCP连接池
2013-10-21 20:10 1431公司的内部服务器,一直是采用的tomcat,连接池也是采用的 ... -
Tomcat把JDBC驱动强行注销的问题
2013-01-26 02:50 2218异常:A web application regist ... -
JVM垃圾收集相关常用参数
2012-12-03 10:49 1792参 数 描 ... -
Memory Analyzer Tool(MAT) 使用基础
2012-11-22 16:17 1318MAT 使用初探 今天线上一个应用的持久区满了,一直没 ... -
Tomcat中URIEncoding的使用
2012-08-10 14:51 1850tomcat5中,为了保证get数据采用UTF8编码,在 ... -
关于Jboss/Tomcat/Jetty的JNDI定义123
2012-05-08 21:15 1774貌似有段时间没来这里忽悠了,今天抽空接着忽悠下 ... -
Maven 简要
2012-03-24 14:20 10471.前言 Maven,发音是[ ... -
使用Jacob操作Office 配置及结构简介
2012-03-10 22:11 78461、介绍 Jacob 是Java-COM ... -
Velocity语法
2012-01-20 16:34 8372Velocity语法 1. 变量 (1)变量 ... -
7个改变世界的Java项目
2011-10-21 09:22 1622Java的开源生态系统是强大而健康的,这是我们(Oreill ... -
Java 开发之小经验
2011-04-17 11:42 928本文是鄙人从发布日期开始收集的一些开发上的小经验。不足之处 ... -
iBatis简记
2011-01-26 15:26 1265<isEqual> 如果参数相等于值则查询条 ... -
Linux下Java程序中文乱码问题研究
2011-01-07 15:00 3136Linux下Java程序中文乱码问题研究 贾金营1 ,贾金 ... -
log4j重复输出log信息原因和解决办法
2010-11-16 09:10 3198log4j的logger(旧版本称logger)是层次结构的, ...
相关推荐
### Jakarta Commons CookBook 学习笔记 #### 一、Commons Lang: EqualsBuilder and HashCodeBuilder **1.1 概述** `EqualsBuilder` 和 `HashCodeBuilder` 是 Apache Commons Lang 包中提供的两个工具类,用于...
学习并熟练掌握《Jakarta Commons Cookbook》中的知识点,开发者不仅可以提升个人技能,还能在实际项目中提高代码质量和开发效率,使Java应用更加健壮和高效。这本书的电子版为开发者提供了随时随地学习的便利,是一...
jakarta-commons 相关依赖包,文件列表: commons-attributes-api.jar commons-attributes-compiler.jar commons-beanutils.jar commons-codec.jar commons-collections.jar commons-dbcp.jar commons-digester.jar ...
Jakarta Commons是Apache软件基金会...通过学习和使用Jakarta Commons Lang,开发者可以显著提高代码的效率和可读性,避免重复编写常见的基础工具代码。同时,源码和API文档能够帮助我们更好地理解和利用这个强大的库。
### Apache Jakarta Commons 使用手册知识点详解 #### 一、概述 《Apache Jakarta Commons 使用手册》是一部详细介绍Apache Jakarta Commons项目下的各种Java组件的专业书籍。该书由Will Iverson编写,旨在为...
在阅读《Jakarta Commons Cookbook》时,你可以学习如何有效地利用这些组件来提升你的Java项目。例如,了解如何使用` FileUtils.copyFile()`方法复制文件,或通过` StringUtils.join()`将数组元素连接成字符串。此外...
jakarta commons-logging 1.1.1
【Jakarta Commons笔记】 Jakarta Commons是Apache软件基金会的一个项目集合,它提供了许多Java开发中常用的工具类和组件。这个项目旨在减少重复的工作,通过共享和重用代码,提高开发效率。Jakarta Commons包含了...
《Jakarta Commons Cookbook》是Java开发者的一份宝贵资源,它包含了一系列实用的工具类和组件,可以帮助开发者在日常编程工作中提高效率。Jakarta Commons是Apache软件基金会的一个项目,旨在为Java社区提供一系列...
除了上述组件外,Jakarta Commons 还包括 BeanUtils、Codec、 Digester 等,它们提供了诸如对象属性映射、编码解码、XML 解析等功能,大大简化了 Java 开发中的常见任务。 通过了解和使用 Jakarta Commons,开发者...
学习Jakarta Commons具有双重意义:一是从应用层面来看,它可以极大地提升开发效率和代码质量;二是从源码层面来看,Jakarta Commons的源码本身就是一笔宝贵的财富,能够帮助开发者深入了解Java编程的最佳实践和技术...
本书是一本介绍apache commons使用的电子书
Digester不是一个XML Parser,它只是对SAX更高层次上的一个封装使用Digester,将XML映射成javaBean. 我们无须了解SAX和DOM的解析过程,只要给Digester添加一些解析规则,就能对一个xml文件进行解析。Digester使用...
《Jakarta Commons在线书架》一书深入探讨了Jakarta Commons框架的核心概念与应用实践,为读者提供了一次全面理解并掌握Jakarta Commons组件的机会。本书由Vikram Goyal编写,版权归属Manning Publications,出版于...
**Jakarta Commons API** 是一个Java开发人员广泛使用的开源库集合,它包含了多个模块,每个模块专注于特定的编程任务,从而简化了Java应用程序的开发。Jakarta Commons是Apache软件基金会的一个项目,它提供了大量...
12. **Commons Digester**: 使用 XML 配置文件映射到 Java 对象,简化 XML 解析和对象创建过程。 13. **Commons Discovery**: 提供工具定位资源,通过模式匹配服务/引用名称和资源名称。 14. **Commons EL**: 提供...
Jakarta Commons-lang API & Source Code Jakarta lang包API帮助文档,并带有源码
**Jakarta Commons 知识点详解...同时,由于 Jakarta Commons 的开源性质,它的源码也是学习 Java 设计模式和最佳实践的好材料。对于希望提升 Java 编程技能的开发者来说,熟悉并掌握 Jakarta Commons 是非常有价值的。