`

Digester学习笔记

    博客分类:
  • J2SE
 
阅读更多

对象栈

  对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相关的信息,被送往org.apache.commons.digester.Digester.sax记录器,记录了Digester收到的SAX的事件的信息。
  2. 其它的所有信息,都被送往org.apache.commons.digester.Digester记录器,这个记录器在调试Digester时打开而在产品中常将其关闭


  假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester=debug org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester.sax=info

 

Digester包中的例子

***********Example.xml**********
<address-book>
  <person id="1" category="acquaintance" try="would be ignored">
    <name>Gonzo</name>
    <email type="business">gonzo@muppets.com</email>
    <gender result="the whole tag would be ignored">male</gender>
  </person>
  <person id="2" category="rolemodel">
    <name>Kermit</name>
    <email type="business">kermit@muppets.com</email>
    <email type="home">kermie@acme.com</email>
  </person>
</address-book>**********Person.java************
import java.util.HashMap;
import java.util.Iterator;
public class Person {
  private int id;
  private String category;
  private String name;
  private HashMap emails = new HashMap();
  // 下面的两个方法的名字中set以后的部分,与<person>的属性名字对映。当从xml文件中识别出<person>的属性 时,如果有要求(即调用过addSetProperties方法),Digester会依据这种对映关系自动调用相应的方法。
  public void setId(int id) {
      this.id = id;
  }
  public void setCategory(String category) {
      this.category = category;
  }
  //对name而言,因为其值来自<name>标签的内容而非属性值,需要用addCallMethod指定识别<name>后的要调用此方法(想自动调用也要可以,需要addBeanPropertySetter,参见第下一个例子)。
  public void setName(String name) {
      this.name = name;
  }
  //同name,此时还要一一指定addEmail的参数值的来源。
  public void addEmail(String type, String address) {
      emails.put(type, address);
  }
  public void print() {
      System.out.println("Person #" + id);
      System.out.println("  category=" + category);
      System.out.println("  name=" + name);
      for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) {
          String type = (String) i.next();
          String address = (String) emails.get(type);
          System.out.println("  email (type " + type + ") : " + address);
      }
  }
}
**********AddressBook.java***********
import java.util.LinkedList;
import java.util.Iterator;
public class AddressBook {
    LinkedList people = new LinkedList();
    public void addPerson(Person p) {
        people.addLast(p);
    }
    public void print() {
        System.out.println("Address book has " + people.size() + " entries");

        for(Iterator i = people.iterator(); i.hasNext(); ) {
            Person p = (Person) i.next();
            p.print();
        }
    }
}
************AddressBookDigester*********
import org.apache.commons.digester.Digester;
/**
 * Usage: java Example1 example.xml
 */
public class AddressBookDigester {
    public static void main(String[] args) {
        if (args.length != 1) {
            usage();
            System.exit(-1);
        }
        String filename = args[0];
        // 创建一个Digester实例
        Digester d = new Digester();
        // 创建AddressBook实例,并将其压入栈顶。
        AddressBook book = new AddressBook();
        d.push(book);
        // 增加规则
        addRules(d);
        // 处理输入的xml文件
        try {
            java.io.File srcfile = new java.io.File(filename);
            d.parse(srcfile);
        }
        catch(java.io.IOException ioe) {
            System.out.println("Error reading input file:" + ioe.getMessage());
            System.exit(-1);
        }
        catch(org.xml.sax.SAXException se) {
            System.out.println("Error parsing input file:" + se.getMessage());
            System.exit(-1);
        }
        
        
        // 将解析出的地址数据打印出来
        book.print();
    }
    
    private static void addRules(Digester d) {
        // 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶
        d.addObjectCreate("address-book/person", Person.class);
        
        // 将<person> 标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将标签属性id与属性设 置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相应的方法。
        // 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属性)。
        d.addSetProperties("address-book/person");

        // 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数
        d.addSetNext("address-book/person", "addPerson");        
        
        // 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。
        // 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数,且参数的值是元素的内容)
        d.addCallMethod("address-book/person/name", "setName", 0);
        
        // 当 遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail方法,addEmail方 法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。
        // 此处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);
    }

    private static void usage() {
        System.out.println("Usage: java Example1 example.xml");
    }
}

运行结果如下(运行时可能需要xml-crimson,一个源sun的XML解析器,可到http://xml.apache.org/crimson/下载)

Address book has 2 entries
Person #1
  category=acquaintance
  name=Gonzo
  email (type business) : gonzo@muppets.com
Person #2
  category=rolemodel
  name=Kermit
  email (type business) : kermit@muppets.com
  email (type home) : kermie@acme.com
分享到:
评论

相关推荐

    digester学习笔记

    Apache Commons Digester 是一个用于处理XML文档的Java库,它允许开发者通过定义一系列规则来将XML数据映射到Java对象的属性或者创建新的Java对象。这个库特别适用于配置文件的解析,因为它简化了从XML到Java对象...

    Digester笔记

    ### Digester概述 Digester是Jakarta项目的Commons子项目之一,主要功能在于提供了一种简单易用的方式来解析XML文档。通过使用Digester,开发者能够避免处理复杂的SAX事件流,使得XML解析过程更加直观和高效。 ###...

    Digester读取XML学习

    在学习过程中,你可以从“Digester笔记”系列文档开始,了解基本的XML解析和对象绑定。然后,尝试阅读“文件合并必读”,探索如何处理复杂的XML结构。实践部分,可以通过解压并研究两个Web应用示例,理解在实际项目...

    velocity学习笔记与struts2整合

    3. commons-digester-1.8.jar - 解析XML配置文件的库。 4. commons-lang-2.1.jar - 常用的Java语言工具包。 5. velocity-1.5.jar - Velocity核心库。 6. velocity-tools-1.4.jar - 提供Velocity的工具支持。 7. ...

    一个简单的jsf例子------JSF2学习笔记1

    **JSF2学习笔记1——理解JavaServer Faces 2.0框架** JavaServer Faces (JSF) 是一种基于组件的Web应用程序开发框架,由Sun Microsystems(现为Oracle Corporation的一部分)开发,旨在简化用户界面构建。JSF2是该...

    JavaEE5学习笔记12-JSF集成AJAX使用经验总结

    ### JavaEE5学习笔记12-JSF集成AJAX使用经验总结 #### 1. JSF (JavaServer Faces) 概览 JavaServer Faces (JSF) 是 Java EE 的一个重要组成部分,它提供了一种构建用户界面的组件框架。JSF 允许开发者创建可重用的...

    struts学习的一点笔记

    在深入探讨Struts框架的学习笔记之前,我们先简要回顾一下Struts框架的基本概念与重要性。Struts是一个开源的MVC(Model-View-Controller)框架,主要用于简化Java Web应用的开发。它提供了一套标准的方式来组织和...

    javaee j2ee src 源码

    在研究源码时,这样的文档可能会包含对源码的简介、使用指南或开发者笔记,对于理解和学习源码内容有着辅助作用。 其次,`apache-tomcat-6.0.14-src`是Apache Tomcat的源代码,Tomcat是一个开源的Java Servlet容器...

Global site tag (gtag.js) - Google Analytics