`
alanwu
  • 浏览: 200995 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Tomcat中xml的解析器Digester 第一篇(共三篇)

阅读更多
Tomcat中server.xml定义了进行服务器的配置, 如JNDI, 最大线程数, 监听端口等。 Tomcat在启动的时候就利用server.xml中的配置初始化Service,Server,Engine,Host。

Tomcat利用的是Digester, Digester其实原来是struts的一个模块, 后来发现这个xml转Java    Object费用有实用性, 于是成为apache的一个common模块。 Tomcat取了Digester中的接口和几个普遍性Rule,并且自己实现了一些Rule.


本文先分析如何使用SAX进行XML转Java, 然后再利用Digester进行XML解析,最后分析Tomcat中的Rule使用。

文章代码比较多, 分三篇。
第一篇分析SAX进行XML转Java; 第二篇利用Digester进行XML解析; 第三篇析Tomcat中的Rule使用。

数据绑定概念:
编组Marshalling)是把内存中的数据转化到存储媒介上的过程。因此在 Java 和 XML 环境中,编组就是把一些 Java 对象转化成一个(或多个) XML 文档。在数据库环境中,则是把 Java 表示的数据存入数据库。显然,编组的秘密在于把 Java 实例中的面向对象结构转化成适用于 XML 的 扁平结构,或者 RDBMS 中的关系结构(使用 Java 技术转换到 OODBMS 实际上很简单)。

解组Unmarshalling)是把数据从存储媒介转换到内存中的过程--正好与编组相反。因此需要把 XML 文档解组到 Java VM 中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确的 Java 代码变量的映射。如果映射是错误的,就不可能正确地访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播得很快。

1. Sax Unmarshaller

SAX(the Simple API for XML)是DOM文档驱动的解析器, 它顺序读取文档并且触发相应的Callback事件。Callback事件有元素开始事件,元素结束事件等。接口org.xml.sax.ContentHandler定义了每个SAX事件, 开发人员有时候不关心所有的事件,可以使用默认的DefaultHandler。

接下来分析如何利用SAX把XML转成Java Object。
为了简单起见, 不定义DTD文件。

例子定义了目录,书本, 杂志和文章类。

首先定义catalog.xml文件
 
<?xml version="1.0"?>

<catalog library="somewhere">

   <book>
      <author>Author 1</author>
      <title>Title 1</title>
   </book>
   
   <book>
      <author>Author 2</author>
      <title>His One Book</title>
   </book>
   
   <magazine>
      <name>Mag Title 1</name>
      <article page="5">
         <headline>Some Headline</headline>
      </article>
      <article page="9">
         <headline>Another Headline</headline>
      </article>
   </magazine>

   <book>
      <author>Author 2</author>
      <title>His Other Book</title>
   </book>

   <magazine>
      <name>Mag Title 2</name>

      <article page="17">
         <headline>Second Headline</headline>
      </article>
   </magazine>

</catalog>



Catalog.java

package benewu.gmail.study.tomcat.digester;

import java.util.Vector;

public class Catalog {
   private Vector books;
   private Vector magazines;

   public Catalog() {
      books = new Vector();
      magazines = new Vector();
   }

   public void addBook( Book rhs ) {
      books.addElement( rhs );
   }
   public void addMagazine( Magazine rhs ) {
      magazines.addElement( rhs );
   }

   public String toString() {
      String newline = System.getProperty( "line.separator" );
      StringBuffer buf = new StringBuffer();

      buf.append( "--- Books ---" ).append( newline );
      for( int i=0; i<books.size(); i++ ){
         buf.append( books.elementAt(i) ).append( newline );
      }

      buf.append( "--- Magazines ---" ).append( newline );
      for( int i=0; i<magazines.size(); i++ ){
         buf.append( magazines.elementAt(i) ).append( newline );
      }

      return buf.toString();
   }
}



Book.java
package benewu.gmail.study.tomcat.digester;

public class Book {
	   private String author;
	   private String title;

	   public Book() {}

	   public void setAuthor( String rhs ) { author = rhs; }
	   public void setTitle(  String rhs ) { title  = rhs; }

	   public String toString() {
	      return "Book: Author='" + author + "' Title='" + title + "'";
	   }
	}


Magazine.java
package benewu.gmail.study.tomcat.digester;

import java.util.Vector;

public class Magazine {
   private String name;
   private Vector articles;

   public Magazine() {
      articles = new Vector();
   }

   public void setName( String rhs ) { name = rhs; }

   public void addArticle( Article a ) {
      articles.addElement( a );
   }

   public String toString() {
      StringBuffer buf = new StringBuffer( "Magazine: Name='" + name + "' ");
      for( int i=0; i<articles.size(); i++ ){
         buf.append( articles.elementAt(i).toString() );
      }
      return buf.toString();
   }
}



Article.java
package benewu.gmail.study.tomcat.digester;

public class Article {
	   private String headline;
	   private String page;

	   public Article() {}

	   public void setHeadline( String rhs ) { headline = rhs; }
	   public void setPage(     String rhs ) { page     = rhs; }

	   public String toString() {
	      return "Article: Headline='" + headline + "' on page='" + page + "' ";
	   }
	}



定义好了类和对应的xml配置, 开始利用catalog.xml进行初始化Catalog吧。

SaxCatalogUnmarshaller继承DefaultHandler, 重写关键的两个分方法:startElement和endElement

SaxCatalogUnmarshaller,java

package benewu.gmail.study.tomcat.digester.unmarshalling;

import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.helpers.DefaultHandler;

import benewu.gmail.study.tomcat.digester.Article;
import benewu.gmail.study.tomcat.digester.Book;
import benewu.gmail.study.tomcat.digester.Catalog;
import benewu.gmail.study.tomcat.digester.Magazine;
 
class SaxCatalogUnmarshaller extends DefaultHandler {
    private Catalog catalog;

    private Stack stack;
    private boolean isStackReadyForText;

    private Locator locator;

    // ----- 

    public SaxCatalogUnmarshaller() {
	stack = new Stack();
	isStackReadyForText = false;
    }

    public Catalog getCatalog() { return catalog; }

    // ----- callbacks: -----

    public void setDocumentLocator( Locator rhs ) { locator = rhs; }

    // ----- 

    /**
     * the [namespace URI], the local name, and the fully [qualified name] of the element. 
     */
    public void startElement( String uri, String localName, String qName,
			      Attributes attribs ) {

	isStackReadyForText = false;

	// if next element is complex, push a new instance on the stack
	// if element has attributes, set them in the new instance
	if( localName.equals( "catalog" ) ) {
	    stack.push( new Catalog() );

	}else if( localName.equals( "book" ) ) {
	    stack.push( new Book() );

	}else if( localName.equals( "magazine" ) ) {
	    stack.push( new Magazine() );

	}else if( localName.equals( "article" ) ) {
	    stack.push( new Article() );
 
	    String tmp = resolveAttrib( uri, "page", attribs, "unknown" );
	    ((Article)stack.peek()).setPage( tmp );
	}
	// if next element is simple, push StringBuffer 
	// this makes the stack ready to accept character text
	else if( localName.equals( "title" ) || localName.equals( "author" ) ||
		 localName.equals( "name"  ) || localName.equals( "headline" ) ) {
	    stack.push( new StringBuffer() );
	    isStackReadyForText = true;
	}
	// if none of the above, it is an unexpected element		 
	else{
	    // do nothing
	}		 
    }

    // ----- 

 
    public void endElement( String uri, String localName, String qName ) {

	// recognized text is always content of an element
	// when the element closes, no more text should be expected
	isStackReadyForText = false;

	// pop stack and add to 'parent' element, which is next on the stack
	// important to pop stack first, then peek at top element!
	Object tmp = stack.pop();
	
	if( localName.equals( "catalog" ) ) {
	    catalog = (Catalog)tmp;
	
	}else if( localName.equals( "book" ) ) {
	    ((Catalog)stack.peek()).addBook( (Book)tmp );

	}else if( localName.equals( "magazine" ) ) {
	    ((Catalog)stack.peek()).addMagazine( (Magazine)tmp );
	    
	}else if( localName.equals( "article" ) ) {
	    ((Magazine)stack.peek()).addArticle( (Article)tmp );
	}
	// for simple elements, pop StringBuffer and convert to String
	else if( localName.equals( "title" ) ) {
	    ((Book)stack.peek()).setTitle( tmp.toString() );

	}else if( localName.equals( "author" ) ) {
	    ((Book)stack.peek()).setAuthor( tmp.toString() );

	}else if( localName.equals( "name" ) ) {
	    ((Magazine)stack.peek()).setName( tmp.toString() );

	}else if( localName.equals( "headline" ) ) {
	    ((Article)stack.peek()).setHeadline( tmp.toString() );
	}
	// if none of the above, it is an unexpected element:
	// necessary to push popped element back!
	else{
	    stack.push( tmp );
	}
    }

    // -----
    
    /*
     *  is called when the parser encounters raw text. 
     */
    public void characters( char[] data, int start, int length ) {

	// if stack is not ready, data is not content of recognized element
	if( isStackReadyForText == true ) {
	    ((StringBuffer)stack.peek()).append( data, start, length );
	}else{
	    // read data which is not part of recognized element
	}
    }
    
    // -----
    
    private String resolveAttrib( String uri, String localName, 
			          Attributes attribs, String defaultValue ) {
	
	String tmp = attribs.getValue( uri, localName );
	return (tmp!=null)?(tmp):(defaultValue);
    }
}




当遇到xml中元素开始标识"<", 会触发startElement, 遇到"/>"触发endElement.

图一分析了SAX解析XML,转换成Java Object的一个实例。

客户端使用将非常简单:

Driver.java

package benewu.gmail.study.tomcat.digester.unmarshalling;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import benewu.gmail.study.tomcat.digester.Catalog;
import benewu.gmail.study.tomcat.digester.DigesterDriver;

public class Driver {
    
    public static void main( String[] args ) {
	Catalog catalog = null;

	try {
		
		URL fileURL = DigesterDriver.class.getResource("catalog.xml");
	    File file = new File(fileURL.getFile());
	    InputSource saxsrc = new InputSource( new FileInputStream( file ) );
	
	    
		System.out.println( "--- SAX ---" );
		SaxCatalogUnmarshaller saxUms = new SaxCatalogUnmarshaller();

		XMLReader rdr = XMLReaderFactory.
		    createXMLReader( "org.apache.xerces.parsers.SAXParser" );
		rdr.setContentHandler( saxUms );
		rdr.parse( saxsrc );

		catalog = saxUms.getCatalog();
		System.out.println( catalog.toString() );
	}catch( Exception exc ) {
		exc.printStackTrace();
	    System.out.println( "Usage: SAX|DOM filename" );
	    System.err.println( "Exception: " + exc );
	}
    }
}



文章利用代码和图分析了SAX将XML转成Java Object。
这样可以使得客户端在XML中定义类的属性, 但是不能改变类。
Digester不但可以使客户在XML中定义类的属性, 可以改变不同类, 并且封装了SAX解析, 定义了各种Rule,利用策略模式进行组装类。

参考:

1 理解 SAX
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84979

2 Java与XML联合编程之SAX篇
http://www0.ccidnet.com/tech/guide/2001/10/08/58_3392.html

[img]
  • 描述: SAX解析XML,转换成Java Object的一个实例
  • 大小: 33.9 KB
分享到:
评论
4 楼 renzhengzhi 2015-05-10  
谢谢分享,正在找这方面的资料。
3 楼 alanwu 2007-12-02  
不好意思, DigesterDriver在第二篇文章里面。http://alanwu.iteye.com/admin/show/143911

在这里只是复用了DigesterDriver来寻找catalog.xml路径的方法
2 楼 mindart 2007-12-02  
以上类中怎么少一个“DigesterDriver.class”类?请楼主贴出来
1 楼 侯风玄黄 2007-11-26  
Thanks ,不错,正在学习这方面的东西。

相关推荐

    利用commons-digester解析xml

    标题“利用commons-digester解析XML”涉及到的是Java开发中的一种处理XML文档的工具——Apache Commons Digester。这个库提供了一种方便的方式来映射XML文档结构到Java对象,从而简化了XML数据的处理过程。 Apache ...

    Java_XML解析之Digester的使用

    Java XML解析中的Digester是一个强大的工具,用于将XML文档转换为Java对象。它最初是为了处理Struts框架的配置文件而设计的,随着时间的发展,它成为一个轻量级且高效的框架,专注于单向转换,即从XML到Java对象。...

    Tomcat7启动分析(三)Digester的使用

    在Tomcat7的启动过程中,涉及到很多内部组件的初始化,其中`Digester`是一个重要的工具,用于解析XML配置文件,将XML结构映射为Java对象。本篇文章将深入剖析`Digester`的使用以及它在Tomcat7启动过程中的作用。 `...

    Digester java解析xml

    1. **初始化 Digester**: 在使用 Digester 之前,我们需要创建一个 Digester 实例,并设置一些基本配置,例如XML解析器的命名空间处理等。然后可以通过 `addRuleSet` 方法添加预定义的规则集,或者通过 `addRule` ...

    digester解析xml的问题.pdf

    Digester 是 Apache Commons 中的一个工具类库,它用于解析 XML 文档,并根据预先定义的规则自动创建和配置 Java 对象。在上述问题中,我们看到一个 XML 文档表示了一个考试,其中包含了多个题目,每个题目有其编号...

    使用Apache的Digester来解析XML文档

    Apache Digester是一个强大的Java库,专门用于将XML文档解析成对象模型。在处理XML到Java对象映射时,它提供了一种简洁的方式,避免了手动编写大量繁琐的XML解析代码。这个工具尤其适用于那些需要频繁从XML配置文件...

    xml解析commons-digester的demo

    下面我们将逐步讲解如何构建和运行一个基于Commons Digester的XML解析示例。 1. **引入依赖** 首先,你需要在项目中引入Apache Commons Digester的库。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖: ```...

    Digester解析XML

    **Digester** 是Apache Commons项目中的一个子项目,主要用于简化XML文档的解析工作。它建立在SAX的基础之上,通过定义一系列的模式(Pattern)和规则(Rule),能够有效地处理复杂的XML结构,从而简化开发者的编程...

    使用Digester解析XML文档示例

    ### 使用Digester解析XML文档示例 #### 一、Digester简介与应用场景 ...通过本篇示例的学习,读者可以了解到Digester的基本使用方法及其在实际开发中的应用,从而更好地利用这一工具解决XML解析问题。

    digester解析xml必备包.rar

    在Java开发中,XML(eXtensible Markup Language)是一种常用的数据交换格式,用于存储和传输数据。...这个“digester解析xml必备包”提供了一整套解决方案,方便开发者在项目中快速集成和使用XML解析功能。

    XML的解析之——使用Digester

    本文将深入探讨如何使用Apache的 Digester 库来解析XML文档,这是一款强大的工具,能够将XML数据映射到Java对象,简化了处理XML的过程。 Digester 是Apache Commons项目的一部分,它提供了一种规则驱动的方法来处理...

    Digester解析XML的小例子(对象嵌套)

    在Java开发中,Struts框架提供了一个强大的工具——Digester,用于解析XML文件并自动创建、配置Java对象。本文将详细介绍如何使用Digester处理具有嵌套结构的XML文档,并通过一个具体的实例——"DigesterXmlTest"来...

    Digester解析XML文件

    本文将深入探讨如何使用Digester解析XML文件,以及在实际项目中如何应用。 首先,让我们了解什么是Apache Commons Digester。这是一个Java库,它的主要功能是读取XML文件,并基于一系列预先定义的规则(Rule),...

    使用digester解析XML

    不错的解析XML的类,主要利用org.apache.commons.digester.Digester;

    使用digester配置rule.xml规则来解析自定义的xml文件-代码

    本篇文章将深入探讨如何使用Digester和`rule.xml`配置文件来解析自定义的XML文件。 首先,让我们了解什么是Apache Digester。Digester是一个开源库,它提供了从XML到Java对象的映射功能。通过定义一系列的“消化...

    digester解析xml

    为了方便地将XML文档解析为Java对象,Apache组织提供了一个名为Digester的工具库,它允许开发者通过规则来映射XML元素到Java对象的属性,大大简化了XML处理的工作。本文将深入探讨digester的工作原理和使用方法。 *...

    Digester读取XML学习

    本篇文章将深入探讨如何使用Digester进行XML解析,并提供相关的学习资源。 【描述】:“Digester读取XML学习” Digester的使用基于一系列预定义或自定义的规则,这些规则决定了XML文档的元素与Java对象之间的映射...

    digester解析xml 所需jar包

    本篇文章将详细介绍如何使用`Digester`解析XML,以及在使用过程中需要的依赖库。 首先,`Digester`的核心功能是通过定义规则来将XML元素与Java对象的属性或方法关联,这样在解析XML时,可以自动创建和填充Java对象...

    org.apache.commons.digester解析XML.rar

    Apache Commons Digester是一个Java库,专门用于将XML文档解析成对象结构。这个“org.apache.commons.digester解析XML.rar”压缩包包含了一个测试工程,它演示了如何使用Digester库来解析XML文件并映射到Java对象上...

Global site tag (gtag.js) - Google Analytics