Getting Start: Apache jakarta commons Digesterkitta XML已经成为了我们开发过程中不可缺少的技术。我们可以用它来描述程序的配置,适配不同的数据格式,甚至作为数据库使用。帮助处理XML的工具很多,它们让我们活得更轻松。Jakarta Commons下的Digester就是一个不错的工具。它提供了一种将XML与Java对象进行映射的方便方法。这么说可能让新手更迷惑,还是举个例子吧!我们有这样一个XML文件: <!-- Memos_2004-01-16.xml --> <?xml version="1.0"?> <memos> <memo> <title>About Jakatar commons Digester</title> <date>2004-01-16 02:05</date> <body>We are working on Digester 1.6-dev.Because it supported read attributes of element.We should pay attention to the releasing of Digester for its changing.</body> </memo> <memo> <title>Ah ha! It's good night!</title> <date>2004-01-16 4:19</date> <body>I has enhanced the basic framework of my app with improved architecture and performance. It's time to sleep. Good night, boys.</body> </memo> </memos> 这是我的备忘录,我用xml作为“数据库”。现在我们想用Java程序来读/写这个“数据库”应该怎么做呢?啊!对了,SAX、DOM……,好了,忘了它们吧!我们有更Easy的办法!我们先来创建一个Memo类,它用来保存一条Memo。它有三个属性用来保存标题、日期以及Memo的正文。我们提供了公共的Setter和Getter,并且我们重载了toString()方法以便查看运行结果。 /* Memo.java */ package kitta.memo; public class Memo { /*-----/ Instance Field(s) /------------------------------------------------*/ private String _title; private String _body; private String _date; /*-----/ Constructor(s) /---------------------------------------------------*/ public Memo() { /* do nothing now */ } /*-----/ Getter(s) & Setter(s) /--------------------------------------------*/ public String getBody() { return _body; } public void setBody(String body) { _body = body; } public String getTitle() { return _title; } public void setTitle(String title) { _title = title; } public String getDate() { return _date; } public void setDate(String date) { _date = date; } /*-----/ Overrided Method(s) /----------------------------------------------*/ public String toString() { StringBuffer buf = new StringBuffer(); buf.append("/t").append(_title); buf.append("/tat/t").append(_date).append("/n/n"); buf.append("/t").append(_body).append("/n"); buf.append("-----------------------------------------------------------/n"); return buf.toString(); } } 然后是Memos类,它实际上是一个Memo对象的集合,完全可以用一个Collection的子类去代替它,但是这里之所以还是使用它主要是为了概念上的清晰。它同样很简单,一个私有属性_memos用来保存所有Memo对象的实例,一个共有方法addMemo()用来添加Memo,toString()方法的目的同上。 /* Memos.java */ package kitta.memo; import java.util.Collection; import java.util.Iterator; import java.util.Vector; public class Memos { /*-----/ Instance Fields /--------------------------------------------------*/ private Collection _memos=new Vector(); /*-----/ Constructor(s) /---------------------------------------------------*/ public Memos() { /* do nothing */ } /*-----/ Getter(s) & Setter(s) /--------------------------------------------*/ public void addMemo(Memo memo) { _memos.add(memo); } /*-----/ Overrided Method(s) /----------------------------------------------*/ public String toString() { StringBuffer buf = new StringBuffer(); buf.append("-----------------------------------------------------------/n"); buf.append(" Memo Application/n"); buf.append(" (").append(_memos.size()).append(" memos total found.)/n"); buf.append("-----------------------------------------------------------/n"); for(Iterator itr = _memos.iterator();itr.hasNext();) { Memo m = (Memo) itr.next(); buf.append(m.toString()); } return buf.toString(); } } 请注意init方法,它告诉Digester如何将XML中的数据映射到我们的Java对象。 package kitta.memo; import java.io.IOException; import java.io.InputStream; import org.apache.commons.digester.Digester; public class MemoApp { /*-----/ Instance Field(s) /------------------------------------------------*/ private Memos _memos; /*-----/ Constructor(s) /---------------------------------------------------*/ public MemoApp() { /* do nothing */ } /*-----/ Private Methods(s) /-----------------------------------------------*/ /** * Initializes the instance of Digester. */ private void init(Digester dgstr) { /* 当遇到memos元素时创建一个Memos对象 */ dgstr.addObjectCreate("memos", Memos.class); /* 当遇到memo元素时创建一个Memo对象 */ dgstr.addObjectCreate("memos/memo", Memo.class); /* 当遇到memos/memo/title元素时,调用当前Memo对象的setTitle方法 */ dgstr.addBeanPropertySetter("memos/memo/title", "title"); /* 当遇到memos/memo/body元素时,调用当前Memo对象的setBody */ dgstr.addBeanPropertySetter("memos/memo/body", "body"); /* 当遇到memos/memo/date元素时,调用当前Memo对象的setDate方法 */ dgstr.addBeanPropertySetter("memos/memo/date", "date"); /* 调用当前的Memos对象的addMemo方法,参数为当前的Memo对象 */ dgstr.addSetNext("memos/memo", "addMemo"); } /** * prints details of memos to standard out. */ private void print() { System.out.println(_memos); } /** * maps the xml data to java object */ private void load(InputStream in) throws Exception { Digester dgstr = new Digester(); init(dgstr); try { _memos = (Memos) dgstr.parse(in); } catch (IOException e) { throw new Exception("Error occured When loading data",e); } } /*-----/ Main Method /------------------------------------------------------*/ public static void main(String[] args) throws Exception { MemoApp mapp = new MemoApp(); /* load xml file from classpath */ mapp.load(MemoApp.class.getResourceAsStream("/kitta/memo/memo.xml")); mapp.print(); } } Digester用"elem/elem/elem"的方式来匹配xml中的元素。这非常直观,实际上我们很早就开始使用类似的方式了。Digester将其称为Pattern。Digester中还有一个重要的概念就是Rule。我们在init方法中所做的就是将Pattern和Rule关联起来。当Digester发现与我们所注册的Pattern匹配的xml元素时,就会调用我们注册时指定Rule来处理这个元素。 环境 以上代码的测试环境为Windows XP、JDK 1.4.2 03、Digester 1.5 Release。 相关资源 Degister官方资源Web site: http://jakarta.apache.org/commons/digester/index.htmlCVS connection: scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons/digester/CVS Web View: http://cvs.apache.org/viewcvs/jakarta-commons/digester/一些其它地方的文章:http://www-106.ibm.com/developerworks/java/library/j-lucene/http://www.javaworld.com/javaworld/jw-10-2002/jw-1025-opensourceprofile.htmlhttp://www.onjava.com/pub/a/onjava/2002/10/23/digester.html 最后 好啦!就这么简单!因为这只是一些基本的应用,它可以帮助你了解Digester,毕竟这只是一个Getting Start吗!要更好的应用,就要更深入的研究。 转自 http://www.javaresearch.org/article/11921.htm