




已阅读5页,还剩14页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Digester学习笔记(一)在windows下开发程序,用M$提供的接口处理.ini文件或管理注册表的键值是非常方便的。在java平台上开发程序,则习惯于以xml 格式的文件来存放系统的配置信息,对这种文件的解析和处理,可以用sax或dom。有没有更简便的方法呢?有,就是用digester模块。Digester是Jakarta 子项目Commons下的一个模块,支持基于规则的对任意XML文档的处理。它最初是Structs项目的一部分,后因其通用性而划归Commons.下载及编译cvs -d :pserver::/home/cvspublic loginpassword: anoncvscvs -d :pserver::/home/cvspublic checkout jakarta-commons/digestercd jakarta-commons/digesterant distDigester的运行依赖下列包:1. 一个遵循Jaxp(1.1版本及以后)的XML解析器2. Jakarta commons beanutils包(1.5版本及以后)3. Jakarta commons collections包(2.1版本及以后)4. Jakarta commons logging包(1.0.2版本及以后) 一个简单的例子假定有两个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文件进行配置用下面几行代码即可完成配置文件解析工作:Digest解析代码注释Digesterdigester = new Digester();digester.setValidating(false);不进行XML与相应的DTD的合法性验证 digester.addObjectCreate(foo, mypackage.Foo);当遇到时创建一个mypackage.Foo对象,并将其放在栈顶digester.addSetProperties(foo);根据元素的属性(attribute),对刚创建的Foo对象的属性(property)进行设置 digester.addObjectCreate(foo/bar, mypackage.Bar);当遇到的子元素 时创建一个mypackage.Bar对象,并将其放在栈顶。 digester.addSetProperties(foo/bar);根据元素的属性(attribute),对刚创建的Bar对象的属性(property)进行设置 digester.addSetNext(foo/bar, addBar, mypackage.Bar );当再次遇到的子元素时创建一个mypackage.Bar对象,并将其放在栈顶,同时调用第二栈顶元素(Foo对象)的addBar方法。Foo foo = (Foo) digester.parse();分析结束后,返回根元素。基本情况熟悉用SAX来处理XML文档的程序员,会发现Digester隐藏了遍历XML元素这些细节,而是提供了更高一层的、更友好的SAX事件接口,从而让程序员的精力放在对数据的处理过程中。使用Digester,须按照以下步骤:1. 创建一个mons.digester.Digester实例。一个解析请求完成后,这个Digester可以被后面复用。但也不要试图在不同的线程中从共享一个 Digester实例。2. 根据需要设置一些配置属性(configuration properties),以控制下一步的解析操作。3. 将一个或几个初始对象(initial object)压入Digester对象栈,本步骤不是必须的。 4. 注册所有的元素匹配模板(elemet matching pattern)。当一个模板被从输入文档中识别出来以后,与其相联系的处理规则(processing rules)被激活。对一个特定的模板,可以定义任意多的规则,当识别出该模板后,这些规则依序依次执行。5. 调用digester.parse()方法,一个XML文档的引用(用多种方式供选择)要传给这个方法。注意,需要捕捉并处理IOException或SAXEception或处理过程中抛出的异常。 元素匹配模板Digester能自动遍历目标XML文档的元素形成的层次结构,这个过程无需程序员参与。程序员的任务是决定,在解析的过程中,当由嵌套的元素形成的一个特定序列被识别出时,如何处理它。用以描述这种序列的机制,就叫元素匹配模板。具体说来,元素和其子元素间,用/相隔,如果一些元素前没有/则其必为根元素。如例:-匹配模板a-匹配模板a/b-匹配模板a/b/c -匹配模板a/b/c-匹配模板a/b-匹配模板a/b/c-匹配模板a/b/c-匹配模板a/b/c字符*表示任意级别,如*/a表示任意级别的都可匹配(不包括根元素级的).熟悉XLST的朋友,对这种思路一定不陌生。从上面的描述,可知某个元素同时满足多个匹配模板是非常可能的,在这种情况下,与各个模板相关联的处理规则(processing rule)的执行顺序如下:对begin或body方法,按照各个rule的注册顺序的先后,对end方法则是注册顺序的反序。处理规则(processing rule)元素匹配模板用以识别什么时候采取行动,处理规则则用以定义行动的内容。从形式上讲,一个处理规则是一个java类,它扩展了mons.digester.Rule类。每个处理规则,实现下列的一个或几个事件处理方法(event method),当相应的模板匹配成功以后,在已定义的某个时刻,这些事件方法会被触发。1. begin(),在一个匹配元素被识别出后的开始时刻被调用,这个元素的所有属性放在一个数据结构中被传递给begin()2. body(),当元素的嵌套内容(如子元素)被识别出时被调用。在解析的过程中,前后的空白被去掉了3. end(),匹配元素的结束时刻被调用。如果子元素也匹配相关的规则,则这些规则的方法需都执行毕,才能达到该元素的结束时刻。 4. finish(),解析结束时被调用,以提供给各个规则以清理临时数据的机会。 在设置digester时,通过调用addRule()方法,来注册一个特定的元素匹配模板以及相应的一个Rule类的实例。如上所述,Rule类中的事件处理方法,会在适当的时间被调用。这个机制,允许动态地生成Rule的实现。另外,digester也提供了一些处理常见情况的处理规则类。1. ObjectCreateRule,当begin()方法被调用时,这个规则类实例化一个指定的java类,并将其压入栈顶。这个被实例化的类的名字,默认是这个规则类构造函数得到的参数,也可以通过指定正在处理的xml元素的属性来传递一个新的类的名字。当end()方法被调用时,栈顶的对象被弹出,Digester中对它的任何引用将被忽略。2. FactoryCreateRule,一个非常有用的ObjectCreateRule的变体。3. SetPropertiesRule,当begin()方法被调用时,digester 使用标准的Java Relection API来识别JavaBean的属性设置方法(setter method),这些方法名称中包含属性(property)的名字,这些属性与XML元素的属性(attribute)匹配,于是这些方法被调用并将相应的属性值(attribute value)传给它们。这些自然的映射可以被重写。建议不要过度使用这项功能,在大多数情况下,使用标准的BeanInfo机制会更好。4. SetPropertyRule,当begin()方法被调用时,digester调用栈顶对象的一个特定的属性设置方法(property setter)并传给它特定的值(property和值分别由两个 attribute命名)。这对XML需要遵循一个指定的DTD时比较有用,你可以设置一个特别的属性(property),虽然在指定DTD没有attribute与其相对应。5. SetNextRule,当end()方法被调用时,digester分析第二栈顶元素,寻找一个特定属性(property)的设置方法 (setter method),并接着调用这个方法,以栈顶的元素作参数。这个规则通常用来在两个对象间建立1对多的关系,所用的方法也常被叫做addChild什么的。6. SetTopRule,当end()方法被调用时,digester分析栈顶元素,寻找一个特定属性(property)的设置方法 (setter method),并接着调用这个方法,以第二栈顶的元素作参数。这个规则通常用来在两个对象间建立1对多的关系,所用的方法也常被叫做setParent 什么的。7. CallMethodRule,这个规则设置当end()被调用时执行的栈顶对象的自定义方法,通过对这个规则的设置,来指定方法的名字、参数的数量以及定义的参数类型的Java类的名字。实际的参数值,来自激活这个方法的元素的子元素。8. CallParamRule,这个规则用来指定CallMethodRule的参数的值的来源,它可以来自一个特定的属性,或子元素的body的内容.9. NodeCreateRule,一个特殊的规则,将对象树的一部分转换成一个DOM结点(Node),并压入栈顶。 对这些标准的规则类,可以创建它们的实例,并调用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学习笔记(二)为便于理解,将笔记的内容结构作了一些调整。对象栈对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此栈的基本操作包括:1. clear(),清空栈的内容2. peek(),返回对栈顶对象的引用3. pop(),将栈顶对象弹出并返回4. push(),将一个新的对象压入栈顶 用栈的原因,就是当识别出一个XML元素的开始时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的结束时,则弹出此对象,并进行相关的处理。 如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建立起一种父子关系,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象).如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。日志(logging)日志是一个调试Digester规则集的非常重要的工具,它可以记录非常丰富的信息,因它在使用Digester之前有必要了解日志是如何工作的。Digester使用Jakarta Commons Logging,这个模块并不是具体的日志实现,而只是一个可设置的接口。可以设置它将各种日志信息传递它自身带的基本记录器,或者传递给其它的更复杂的日志工具。具体请参考commons logging的文档,或Jakarta Commons Logging学习笔记 Digester主要使用两个记录器: 1. SAX相关的信息,被送往mons.digester.Digester.sax记录器,记录了Digester收到的SAX的事件的信息。 2. 其它的所有信息,都被送往mons. digester.Digester记录器,这个记录器在调试Digester时打开而在产品中常将其关闭 假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下: mons.logging.Log=mons.logging.impl.SimpleLog mons.digester.Digester=debug mons.digester.Digester.sax=infoDigester包中的例子*Example.xml*Gonzo maleK*Person.java*importjava.util.HashMap;importjava.util.Iterator;publicclassPersonprivateintid;privateStringcategory;privateStringname;privateHashMapemails=newHashMap();/下面的两个方法的名字中set以后的部分,与的属性名字对映。当从xml文件中识别出 的属性时,如果有要求(即调用过addSetProperties方法),Digester会依据这种对映关系自动调用相应的方法。publicvoidsetId(intid)this.id=id;publicvoidsetCategory(Stringcategory)this.category=category; /对name而言,因为其值来自标签的内容而非属性值,需要用addCallMethod指定识别后的要调用此方法(想自动调用也要可以,需要addBeanPropertySetter,参见第下一个例子)。publicvoidsetName(Stringname)=name;/同name,此时还要一一指定addEmail的参数值的来源。publicvoidaddEmail(Stringtype,Stringaddress)emails.put(type,address);publicvoidprint()System.out.println(Person#+id);System.out.println(category=+category);System.out.println (name=+name);for(Iteratori=emails.keySet().iterator();i.hasNext();)Stringtype=(String)i.next();Stringaddress=(String)emails.get(type);System.out.println(email(type+type+):+address);*AddressBook.java*importjava.util.LinkedList;importjava.util.Iterator;publicclassAddressBookLinkedListpeople=newLinkedList();publicvoidaddPerson(Personp)people.addLast(p);publicvoidprint()System.out.println(Addressbookhas+people.size()+entries); for(Iteratori=people.iterator();i.hasNext();)Personp=(Person)i.next();p.print();*AddressBookDigester*mons.digester.Digester;/*Usage:javaExample1example.xml*/publicclassAddressBookDigesterpublicstaticvoidmain(Stringargs)if(args.length!=1)usage();System.exit(-1);Stringfilename=args0;/创建一个Digester实例Digesterd=newDigester();/创建AddressBook实例,并将其压入栈顶。AddressBookbook=newAddressBook();d.push(book);/增加规则addRules(d);/处理输入的xml文件tryjava.io.Filesrcfile=newjava.io.File(filename);d.parse(srcfile);catch(java.io.IOExceptionioe)System.out.println(Errorreadinginputfile:+ioe.getMessage();System.exit(-1);catch( org.xml.sax.SAXExceptionse)System.out.println(Errorparsinginputfile:+se.getMessage();System.exit(-1);/将解析出的地址数据打印出来book.print();privatestaticvoidaddRules(Digesterd)/当遇到时,创建类Person的一个实例,并将其压入栈顶d.addObjectCreate(address-book/person,Person.class);/将标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相应的方法。/如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个的try属性)。d.addSetProperties(address-book/person);/调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数d.addSetNext(address-book/person,addPerson);/当遇到的子元素时,调用栈顶对象(Person实例)的setName方法。/此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数,且参数的值是元素的内容)d.addCallMethod(address-book/person/name,setName,0);/当遇到的子元素时,调用栈顶对象(Person实例)的addEmail 方法,addEmail方法有两个参数,取值分别来自的属性type的值和本身的内容。/此处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);privatestaticvoidusage()System.out.println(Usage:javaExample1example.xml);运行结果如下(运行时可能需要xml-crimson ,一个源sun的XML解析器,可到/crimson/下载) Addressbookhas2entriesPerson#1category=acquaintancename=Gonzoemail(typebusiness):Person#2category=rolemodelname=Kermitemail(typebusiness):email(typehome):Digester学习笔记(三)总觉得,Digester不仅仅能作配置文件解析,而且可以作得更多。配置属性Digester用来解析应用系统的配置文件,其本身也有很可配置的属性。属性描述classLoader 指定类装载器(class loader)。ObjectCreateRule 和 FactoryCreateRule两个规则中,需要动态加载一些类(如那些盛放XML解析出来的数据的javaBean等),装载器可以在次指定。如果不指定,对这此类的加载将会利用线程上下文中的加载器(当useContextClassLoader值为真时)或利用加载Digester的那个加载器。errorHandler 指定 SAX ErrorHandler,以在出现此类错误时调用。默认情况下,任何解析错误都会被记入日志,Digest会继续进行解析。 namespaceAware 一个布尔值,为真时对XML文件的解析时会考虑元素的域名空间(如不同的域名空间的同名元素会视为不同的元素)ruleNamespaceURI 指定后续加入的规则所属的命名空间,如果此值为null,则加入的规则不与任何命名空间相联系。rules 设定规则模板与XML元素的匹配处理程序。由于这个匹配程序是插件式的,所以匹配工作的完成可以用用户定义的匹配程序未完成。默认情况下,使用Digester提供的匹配器。 useContextClassLoader 一个布尔值,为真时FactoryCreateRule 和 ObjectCreateRule 两个规则中对类的装载将会采用当前线程上下文中指定的加载器。默认情况下,对类的动态加载会利用加载 Digester的那个装载器。 validating 一个布尔值,为真时解析器会根据DTD内容对XML文档进行合法性检查,默认值是假,解析器只是检查XML是否格式良好(well formed). 除了上述属性外,还可以注册一个本地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类来开发规则集类。如例: publicclassMyRuleSetextendsRuleSetBasepublicMyRuleSet()this();publicMyRuleSet(Stringprefix)super();this.prefix=prefix;spaceURI =/MyNamespace;protectedStringprefix=null;publicvoidaddRuleInstances(Digesterdigester)digester.addObjectCreate(prefix+foo/bar,com.mycompany.MyFoo);digester.addSetProperties(prefix+foo/bar);可以这样使用这个规则集 Digesterdigester = new Digester();. 一些配置Digester .digester.addRuleSet(new MyRuleSet(baz/);带命名
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 物业公司合同管理工作流程
- 管理办法需要重新修订
- 粮食仓储资金管理办法
- 供应链采购审批流程简化管理表
- 李老师讲故事550字12篇范文
- 注册安全工程师初级题库安徽及答案解析
- 数据分析与应用策略思考与写作训练课程教案
- 校园欺凌信息公开与处理措施
- 陕西省西安市2025-2026学年高二上学期开学英语试题(含答案含听力原文无音频)
- 高三开放的中国作文8篇
- 2025年医卫类病理学技术(中级)专业知识-专业实践能力参考题库含答案解析(5套试卷)
- 2025上海科技馆事业单位工作人员招聘10人笔试备考题库及答案解析
- 八年级语文上册期末考点专题17 新闻阅读(解析版)
- 【初二】【八年级】【道法】2025【秋】上学期开学第一课【统编版】(课件)
- 监狱消防安全应急预案
- 军事类面试题目及答案
- 2025巡护员考试题库及答案
- 产科专科护士结业汇报
- (完整版)采购评审专家考试试题库(附完整答案)
- 河北广电频道管理办法
- 2025年中式烹调师(技师)考试题库附答案
评论
0/150
提交评论