Apache Digester(-)

一、简介

    Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应具有更广泛的用途,所以很快它就在Jakarta Commons项目(用于提

供可重用的Java组件库)中有了一席之地。

    如今Digester随着Struts的发展以及其的公用性而被提到commons中独自立项,是apache的一个组件 apache commons-digester.jar,通过它可以很方便的从xml文件生成java对象.你不用再象以前通过jdom或者Xerces去读取一个

document对象.(jdom和Xerces仍然有它们的用武之地及强大之处,在其它应用里你也少不了它们) 。


二、工作原理

    Digester由"事件"驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。工作原理如下:

    Digester底层采用SAX解析XML文件,所以很自然的,对象转换由"事件"驱动,即在识别出特定XML元素时(实际被细分为begin、body、end、finish四个时点),将执行特定的动作,比如创建特定的Java对象,或调用特定对象的方法

等。此处的XML元素根据匹配模式(matching pattern)识别,而相关操作由规则(rule)定义。在转换过程中,Digester维持了一个对象栈,可以看作对象转换的工作台,用来存放转换中生成的、或是为转换临时创建的Java对象。对输入XML

文件作了一趟完整的扫描后,对象栈的栈顶元素即为目标对象。由于Digester屏蔽了SAX解析的细节,使用者仅需关注转换操作本身,大大简化了转换操作。

三、Hello World

1. 用来演示的两个类 Foo.java 和 Bar.java

Foo.java

package com.desmond.generator.run.digester;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Foo {
	private String name;
	private List<Bar> barList = new ArrayList<Bar>();

	public void addBar( Bar bar ) {
		barList.add(bar);
	}

	public Bar findBar( int id ) {
		Bar bar = null;
		for(Bar b : this.barList) {
			if(id == b.getId()) {
				bar = b;
				break;
			}
		}
		
		return bar;
	}

	public Iterator<Bar> getBars() {
		return this.barList.iterator();
	}

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

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

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("Foo [name=" + name + ", barList=");
		Iterator ite = this.getBars();
		while(ite.hasNext()) {
			sb.append("\r\t\t" + ite.next().toString());
		}
		
		return sb.toString();
	}

}

Bar.java:

package com.desmond.generator.run.digester;

public class Bar {
	private int id;
	private String title;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	@Override
	public String toString() {
		return "Bar [id=" + id + ", title=" + title + "]";
	}
	
}

2.需要被解释的XML文件 foobar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<foo name="The Parent">
	<bar id="123" title="The First Child" />
	<bar id="456" title="The Second Child" />
</foo>

3.测试类 Test.java

package com.desmond.generator.run.digester;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester.Digester;
import org.apache.log4j.Logger;
import org.xml.sax.SAXException;

import com.desmond.generator.util.GeneratorHelper;

public class Test {
	private static Logger log = Logger.getLogger(Test.class.getName());

	public static void main(String[] args) {
		Digester digester = new Digester();
		digester.setValidating(false);
		digester.addObjectCreate("foo", "com.desmond.generator.run.digester.Foo");
		digester.addSetProperties("foo");
		digester.addObjectCreate("foo/bar", Bar.class);
		digester.addSetProperties("foo/bar");
		digester.addSetNext("foo/bar", "addBar", "com.desmond.generator.run.digester.Bar");
		
		InputStream input = GeneratorHelper.class.getClassLoader().getResourceAsStream(
				"com/desmond/generator/run/digester/foobar.xml");
		try {
			Foo foo = (Foo) digester.parse(input);
			log.info(foo);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

4.流程

a.当遇到最外层元素<foo>时,创建一个 com.desmond.generator.run.digester.Foo 对象新的实例(即代码"digester.addObjectCreate("foo", "com.desmond.generator.run.digester.Foo");"),并且把他压入对象栈;当遇到</foo>时,这个Foo对象将会出栈。

b."digester.addSetProperties("foo");" 为这个刚刚被创建的对象的属性设值(根据XML文件<foo>元素的值来设定)。

c.当遇到嵌套元素<bar>时,为Bar创建一个新的实例,压入对象栈中,当遇到</bar>时,把这个对象抛出栈。

d."digester.addSetProperties("foo/bar");",为Bar这个对象的属性设值(根据XML文件<foo>元素的值来设定)。注意,设值的时候,类型会自动转换(比如bar中的id 由String -->int),

用到了apache的另一个project "commons-beanutils".

e."digester.addSetNext("foo/bar", "addBar", "com.desmond.generator.run.digester.Bar");", 意思为调用对象栈中"next-to-top"元素(本例中就是Foo对象的实例)的addBar方法,

并把对象栈中栈顶对象作为参数传给他,注意,这个对象必须是“com.desmond.generator.run.digester.Bar”类型的。

f.一旦解析完成,对象栈中的第一个元素(本例中为Foo的实例)将会返回给你,他的属性和子类都是有值的。


5.Output:

 Foo [name=The Parent, barList=
	Bar [id=123, title=The First Child]
	Bar [id=456, title=The Second Child]
     ]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值