码迷,mamicode.com
首页 > 编程语言 > 详细

Digester : a java object builder based xml

时间:2015-06-09 11:12:19      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

 

         在Java编程中,配置文件大多数都是用xml文件来组织的。所以在Java语言中处理xml的工具就特别多。

在java中解析XML的几种方式,应该都是知道的。在这些解析技术的基础之上,又发展了几种优秀Object/XML关联的技术,例如有一种对象绑定技术(JAXB),再例如Digester。这里就来简单的了解一下Digester技术。

         如果说对Digester运用最为高超的应用,非Tomcat莫属了。Tomcat中几个重要的配置文件(如server.xml、web.xml、context.xml),都是使用Digester来完成xml到Java对象的转换的。

         Digester只需要设置好相应的处理规定,就可以得到想要的对象结构。它的最大优点就是可以自定义各种处理规则。然而,如果不能明白Digester的设计原理,那你就只使用Digester给你提供的几种规则了。

 

Digester例子

 

Java对象设计:

package com.fjn.frame.digester.list;

public class XxObject {
    private String id;
    private String name;
    private int num;

    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 getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "id: " + id + "\tname: " + name + "\tnum: " + num;
    }
}

这个类没有任何的含义,只是我随便写的而已。


一个简单的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<XxObjects>
    <XxObject id="id001" name="hello1" num="1" />
    <XxObject id="id002" name="hello2" num="2" />
    <XxObject id="id003" name="hello3" num="3" />
    <XxObject id="id004" name="hello4" num="4" />
    <XxObject id="id005" name="hello5" num="5" />
    <XxObject id="id006" name="hello6" num="6" />
    <XxObject id="id007" name="hello7" num="7" />
    <XxObject id="id008" name="hello8" num="8" />
    <XxObject id="id009" name="hello9" num="9" />
</XxObjects>

 

接下来的任务就是将这个XML文件转换为一个对象集合了。 

 

package com.fjn.frame.digester.list;

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

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.digester3.Digester;
import org.junit.Test;
import org.xml.sax.SAXException;

public class Convertor {
    @Test
    public void test() throws ParserConfigurationException, SAXException,
            FactoryConfigurationError, IOException {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        Digester digester = new Digester(parser);
        digester.addObjectCreate("XxObjects", "java.util.LinkedList");

        digester.addObjectCreate("XxObjects/XxObject",
                "com.fjn.frame.digester.list.XxObject");
        digester.addSetProperties("XxObjects/XxObject");
        // digester.addSetNext("XxObjects/XxObject", "add");
        digester.addRule("XxObjects/XxObject", new AddToCollectionRule());

        List<XxObject> ret = digester.parse(Convertor.class
                .getResourceAsStream("XxObjects.xml"));
        for (XxObject obj : ret) {
            System.out.println(obj);
        }
    }
}

AddToCollectionRule规则是我自定义的规则: 

package com.fjn.frame.digester.list;

import java.util.Collection;

import org.apache.commons.digester3.Rule;
import org.xml.sax.Attributes;

public class AddToCollectionRule extends Rule {
    @Override
    public void begin(String namespace, String name, Attributes attributes)
            throws Exception {
        Object top = this.getDigester().peek();
        Object o = this.getDigester().peek(1);
        if (o != null) {
            Collection colls = (Collection) o;
            System.out.println(top);
            colls.add(top);
        }
    }

}

程序运行结果: 

id: id001	name: hello1	num: 1
id: id002	name: hello2	num: 2
id: id003	name: hello3	num: 3
id: id004	name: hello4	num: 4
id: id005	name: hello5	num: 5
id: id006	name: hello6	num: 6
id: id007	name: hello7	num: 7
id: id008	name: hello8	num: 8
id: id009	name: hello9	num: 9
id: id001	name: hello1	num: 1
id: id002	name: hello2	num: 2
id: id003	name: hello3	num: 3
id: id004	name: hello4	num: 4
id: id005	name: hello5	num: 5
id: id006	name: hello6	num: 6
id: id007	name: hello7	num: 7
id: id008	name: hello8	num: 8
id: id009	name: hello9	num: 9

使用Digester将xml转为java对象,就是这么简单。 

使用起来如此简单,它是怎么做到的呢?

 

 

Digester设计原理

 

  如果是使用DOM解析的方式,我相信只要你了解DOM树,你就肯定能够完成这个轻松的任务,这也是程序员们更加容易接受DOM解析的原因。但是,设想一下,如果让你来将一个XML文件使用SAX解析的方式,转换为Java对象,你会怎么做呢?

     我在看Digester的源码之前,就做过这样的设想。因为SAX解析的方式中,我们使用的最多的应当是startElement和endElement了。SAX解析是基于事件的,遇到一个开始元素,就执行startElement方法,遇到一个结束元素就执行endElement方法。

  一般来说一个XML元素就对应一个Java对象,XML元素的属性就对应的是Java对象的属性。遇到一个元素开始,就可以根据元素名称来创建出对象。根据元素的属性来设置对象的属性。这个了是很简单的,但是在end一个元素后,也就是对象创建完成后,怎么来存储呢?总不能解析完成,生成了很多对象,我一个也拿不到,那解析它有何用呢。可以考虑一个复杂的XML,例如tomcat的server.xml文件,Server\Service\Engine等有对象是嵌套的,创建一个对象Service后,怎么将它设置到Server中呢?创建一个对象Engine后,怎么将它设置到Service中呢。完成这个工作,就必然要使用到一个数据结构:Stack。如果你能想到这里,Digester你就学会了80%了。

 

Java对象在startElement中创建并入栈,在endElement中完成所有操作并出栈。

 

例子说明

         在上面的例子中,解析到根元素时,会创建出一个LinkedList,然后入栈。因为没有到结束元素,所以它肯定会在栈里,并且是在最下面。然后是解析每个XxObject了。在解析XxObject元素时,都要有3个操作,它们是依次进行的:

1)创建XxObject对象。入栈,那么这个对象肯定是在栈顶了。

2)设置属性。Digester使用的是BeanUtils工具来完成属性的设置的,所以java类在设计时, 是需要 getter和setter的。

3)调用我自定义的AddToCollection规则了。执行这个规则也很简单,取得当前对象(栈顶元素),再取出从栈顶起第二个元素,也就是LinkedList。然后就可以添加到集合中了。

4)endElement,对象出栈,栈中只剩下LinkedList对象。

 最后遇到XxObejcts的end,它就是解析到最后一刻时栈底。返回的什就是栈底对象。所以结果就是一个List了。

 我自定义的那个AddToCollection规则,只是想用于说明如何Digester的原理,以及如何使用自定义规则。其实像这个的常用的规则,Digester已经定义好了,SetNetRule。

 

到这里,这篇文章的主要内容已经说完了。至于如何使用Digester中的各种Rule,还需要靠自己去了解了。

下面附加一张类图:

 技术分享

 

Digester : a java object builder based xml

标签:

原文地址:http://www.cnblogs.com/f1194361820/p/4562636.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!