Java开发网 Java开发网
注册 | 登录 | 帮助 | 搜索 | 排行榜 | 发帖统计  

您没有登录

» Java开发网 » Java程序分享区  

按打印兼容模式打印这个话题 打印话题    把这个话题寄给朋友 寄给朋友    该主题的所有更新都将Email到你的邮箱 订阅主题
reply to topicflat modethreaded modego to previous topicgo to next topicgo to back
作者 using Jakarta commons-digester 简单实现XML JavaObject Mapping
jamesfeng2





发贴: 41
于 2004-08-17 21:15 user profilesend a private message to userreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
commons digester 是专门处理 xml configuration 配置文件的.我想大家对于 XML 的了解应该不会太陌生, 越来越多人开发程序使用的配置, 都用 xml 来撰写,但是呢, 每次都要通过 parser 来取得数据using DOM, SAX, 会觉得重复开发时间的浪费.

commons digester 就是让你配置一个 XML 转到 Java Object 对应的程序, 当一些 XML 中特定的属性将会触发一些被称为 rules 的动作, 有一些属性是已经被定义好了, 当然你也可以建立自己所需要的.

commons digester big advantage is using Matching Patterns, forget about parent/child relationships among tags. The pattern is datasources/datasource, datasources/datasource/name, datasources/datasource/driver, datasources/datasource/url,datasources/datasource/username, datasources/datasource/password. This is an easy and developer-friendly usage to precisely convey the tag to which you want to refer

I demostrate how to use by following examples, we using: sample.xml, Datasource.java, Datasources.java, DigesterTest.java

-------------------------------------------------------------------------------------------------------
Digester 通常是用在解析 XML 配置文件, 假如我们有这样的配置文件:
sample.xml
=======

<?xml version="1.0"?>
<datasources>
<datasource>
  <name>HsqlDataSource</name>
  <driver>org.hsqldb.jdbcDriver</driver>
  <url>jdbc:hsqldb:hsql://localhost</url>
  <username>jamesfeng2</username>
  <password>jamesfeng2</password>
</datasource>
<datasource>
  <name>OracleDataSource</name>
  <driver>oracle.jdbc.driver.OracleDriver</driver>
  <url>jdbc:oracle:thinAngrylocalhost:1521:orcl</url>
  <username>scott</username>
  <password>tiger</password>
</datasource>
</datasources>

Datasource.java will hold the details source we can set or get.
==========

public class Datasource {

  private String name,driver,url,username,password;

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

  public String getName() {
    return name;
  }

  public void setDriver(String driver) {
    this.driver = driver;
  }

  public String getDriver() {
    return driver;
  }

  public void setUrl(String url) {
    this.url = url;
  }

  public String getUrl() {
    return url;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getUsername() {
    return username;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public String getPassword() {
    return password;
  }
  
  public String toString(){
    StringBuffer buf = new StringBuffer();
    buf.append("\t").append(name);
    buf.append("\t").append(driver);
    buf.append("\t").append(url);
    buf.append("\t").append(username);
    buf.append("\t").append(password);
    return buf.toString();
  }

}
  

Datasources.java is a collection of Datasource.java and override toString()
==========
public class Datasource {

  private String name,driver,url,username,password;

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

  public String getName() {
    return name;
  }

  public void setDriver(String driver) {
    this.driver = driver;
  }

  public String getDriver() {
    return driver;
  }

  public void setUrl(String url) {
    this.url = url;
  }

  public String getUrl() {
    return url;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getUsername() {
    return username;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public String getPassword() {
    return password;
  }
  
  public String toString(){
    StringBuffer buf = new StringBuffer();
    buf.append("\t").append(name);
    buf.append("\t").append(driver);
    buf.append("\t").append(url);
    buf.append("\t").append(username);
    buf.append("\t").append(password);
    return buf.toString();
  }

}

DigesterTest.java is driver core class. 首先, 必须先建立 digester 的 instance by addObjectCreate(), 接著将你所需要的数据addCallMethod(), 放到 Digester 的对象堆叠中push(), 增加一些执行的规则addCallParam(), 最后就可以解析这个文件了parse().
==============

import org.apache.commons.digester.*;
import java.io.*;

public class Digesters {

private Datasources datasource;
private void init(Digester dgstr)
{
/* 当遇到datasources元素时创建一个datasources对象 */
dgstr.addObjectCreate("datasources", Datasources.class);

/* 当遇到datasource元素时创建一个datasource对象 */
dgstr.addObjectCreate("datasources/datasource", Datasource.class);
/* 当遇到datasources/datasource/name元素时,调用当前datasource对象的setName方法 */
dgstr.addBeanPropertySetter("datasources/datasource/name", "name");
/* 当遇到datasources/datasource/driver元素时,调用当前datasource对象的setDriver */
dgstr.addBeanPropertySetter("datasources/datasource/driver", "driver");
/* 当遇到datasources/datasource/url元素时,调用当前datasource对象的setUrl方法 */
dgstr.addBeanPropertySetter("datasources/datasource/url", "url");
/* 当遇到datasources/datasource/userName元素时,调用当前datasource对象的setUserName */
dgstr.addBeanPropertySetter("datasources/datasource/username", "username");
/* 当遇到datasources/datasource/password元素时,调用当前datasource对象的setPassword方法 */
dgstr.addBeanPropertySetter("datasources/datasource/password", "password");

/* 调用当前的datasources对象的addDtasource方法,参数为当前的datasource对象 */
dgstr.addSetNext("datasources/datasource", "addDatasource");
}
  private void print(){
  System.out.println(datasource);
  }
  
  private void load(InputStream in) throws Exception{
    Digester dgstr = new Digester();
    init(dgstr);
    
    try {
     datasource =(Datasources)dgstr.parse(in);
    } catch (IOException e) {  
    throw new Exception("Error whne");
        }
    }
    public static void main(String []args) throws Exception{
    Digesters digesters = new Digesters();
    digesters.load(Digesters.class.getResourceAsStream("sample.xml"));
    digesters.print();
    }
}

final result:
===========

RSSDigester
========
RSS 在 Portal 中是非常常见到的 webservice 格式, 通常是一些新闻发布的标准, 相关的内容, 你可以使用 RssDigester 自己写 parse, 或利用已经实作好的 Channel, Image, Item, TextInput 等等. 先了解一下 RSS 的格式, 使用起来应该就可以得心应手 !!

xmlrules 制定 Digester 中的 rules
=======================

当你打开原码目录中, org/apache/commons/digester/ 下有一个 digester-rules.dtd . 这个 DTD 文件就是在定义 Digester 该如何解析你传入的 XML 文件, 你也可以自己定义相关的 patterns , 写在 digester-rules.xml 中, 让 Digester 可以根据你的需要去解析数据. 这样做可以减少程序中, 必须特别写 addObjectCreate, addCallMethod 等等 method. 不过, 我还没有见到目前有任何 project 采用这种做法.

<?xml version="1.0"?>
<!DOCTYPE digester-rules SYSTEM "digester-rules.dtd">

<digester-rules>
  <object-create-rule pattern="*/foo" classname="Foo"/>
  <set-properties-rule pattern="*/foo"/>
</digester-rules>

相关书目或相关文章

TheServerSide:
http://www.theserverside.com/articles/article.tss?l=Digester
IBM:
http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html
Jakarta Commons:
http://jakarta.apache.org/commons/index.html
Jakarta Commons Digester:
http://jakarta.apache.org/commons/digester.html
Simplify XML file processing with the Jakarta Commons Digester :
http://jakarta.apache.org/commons/digester/api/index.html

===================
SCJP,SCWCD,SCBCD



作者 Re:using Jakarta commons-digester 简单实现XML JavaObject Mapping [Re:jamesfeng2]
jamesfeng2





发贴: 41
于 2004-08-17 21:29 user profilesend a private message to userreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
I like itSmile


作者 Re:using Jakarta commons-digester 简单实现XML JavaObject Mapping [Re:jamesfeng2]
jamesfeng2





发贴: 41
于 2004-08-18 22:40 user profilesend a private message to userreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
在前面的内容中,我用程序代码的方式指定模式和规则,这些模式和规则都是在编译的时候就已经确

定,虽然从概念上来讲比较简单,但却不能说尽善尽美:Digester框架的总体目标是在运行时识别和

处理各种数据结构,但如果我们用编程的方法指定模式和规则,则所有行为在编译时已经固定!如果

Java源程序中包含了大量固定的字符串,通常意味着程序在执行某些配置操作,这部分操作可以被(

或许是应该被)延迟到运行时进行。


org.apache.commons.digester.xmlrules包解决了这个问题。这个包提供了一

个DigesterLoader类,它能够从XML文档读取模式/规则对,返回配置好的Digester对象。用来配

置Digester对象的XML文档必须遵从digester-rules.dtd,这个DTD是xmlrules包的一部分。

下面就是本文例子的配置文件samplexmlRule.xml。有几点必须说明。
首先,模式可以用两种方式指定:或者使用<pattern>元素,或者通过代表规则的XML元素的属

性。这两种办法可以混合使用,且<pattern>元素是可以嵌套的。其次,<alias>元素

和<set-properties-rule>一起使用,用来把XML属性映射到Bean属性。最后,就当前发行的Digester

软件包而言,我们不能在配置文件中指定BeanPropertySetterRule,正如前面所介绍的,我们

用CallMethodRule来达到同样的目标。

samplexmlRule.xml ( 增加 )
==================
<?xml version="1.0"?>
<digester-rules>
<pattern value="datasources">
<object-create-rule classname="digersterTwo.Datasources" />
<set-properties-rule />
<pattern value="datasource">
<object-create-rule classname="digersterTwo.Datasource" />
<set-properties-rule />
<call-method-rule pattern="name" methodname="setName" paramcount="0" />
<call-method-rule pattern="driver" methodname="setDriver" paramcount="0"/>
   <call-method-rule pattern="url" methodname="setUrl" paramcount="0" />
<call-method-rule pattern="username" methodname="setUsername" paramcount="0"/>
<call-method-rule pattern="password" methodname="setPassword" paramcount="0"/>
<set-next-rule methodname="addDatasource" />
</pattern>
</pattern>
</digester-rules>

现在,所有实际的操作都转移到了Digester和DigesterLoader类,XmlRulesDriver类就变得相

当简单。运行下面的Digestersxml.java时,第一个是Create Digester using rules defined in

samplesxmlRule.xml,第二个//Parse academy.xml using the Digester to get an instance of

Academy(注意,DigesterLoader不是从File或者org.xml.sax.InputSource读取rules.xml文件,而

是要求指定一个URL,因此,下面代码中File引用被转换成了等价的URL)。

Digestersxml.java ( 替换, 代替 ) Digesters.java
============ ==============
package digersterTwo;
import java.io.File;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;

public class Digestersxml {
  public static void main(String[] args) throws Exception {
    Digestersxml xmlDigest = new Digestersxml();
    xmlDigest.digest();
  }

  public void digest() throws Exception {
    //Create Digester using rules defined in samplesxmlRule.xml
   Digester digester = DigesterLoader.createDigester((new         

File("samplexmlRule.xml")).toURL());

    //Parse academy.xml using the Digester to get an instance of Academy
    Datasources a = (Datasources) digester.parse(Digestersxml.class
          .getResourceAsStream("sample.xml"));

    System.out.printlnAngel;
  }
}

一些认识 & 结束语:
===================

  通过看材料,尤其在学习Digester包中的Catalog例子以后,有一些认识:
  1、由于xml对属性名字的定义要求,与Java中对方法名字的定义要求不一致,导致出现不能自动

映射的情况,如year-made标签属性,就不可能有方法setYear-made;
  2、对于根元素,与其子元素建立联系,有几种办法:一种是先生成根元素实例,压入栈,然后

解析,将调用方法规则建立联系;另一种是解析的过程中第一个创建它,然后用getRoot的方法得到


  3、如果某对象类构造都要参数,则此时需要扩展AbstractObjectCreationFactory类为这种对象

建立一个Factory,在这个Factory中取得初始化参数值然后再创建一个对象实例。
  4、设有某个标签,要想自动用该标签子元素的内容填充该标签对应的对象的属性,则需要

用digester.setRules(new ExtendedBaseRules()),然后addRules(),然后再调

用addBeanPropertySetter("bala/lala/?");进行规则定义,注意此模板中有通配符。
  5、如果对象的属性是整型,则Digester自动将xml文件中字符串值转换为整型。
  6、在指明要digester考虑命名空间之后,如果不会引起歧义,完全可以忽略命名空间的存在,

除非你要针对特定的命名空间进行特定的处理
7、我们简单地提及了通过扩展Rule类开发定制规则的问题。按照习惯,Digester类提供

了push()、peek()和pop()方法,使得开发者能够自由地直接操作解析栈。



====================
SCJP,SCWCD,SCBCD



作者 Re:using Jakarta commons-digester 简单实现XML JavaObject Mapping [Re:jamesfeng2]
Julian13





发贴: 387
于 2004-08-27 16:40 user profilesend a private message to userreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
according to Digester's JavaDoc,
this part of the rule:
jamesfeng2 wrote:
<call-method-rule pattern="name" methodname="setName" paramcount="0" />
<call-method-rule pattern="driver" methodname="setDriver" paramcount="0"/>
   <call-method-rule pattern="url" methodname="setUrl" paramcount="0" />
<call-method-rule pattern="username" methodname="setUsername" paramcount="0"/>
<call-method-rule pattern="password" methodname="setPassword" paramcount="0"/>

is the same as
jamesfeng2 wrote:
<set-properties-rule />

as long as the name of attribute has the corresponding getter/setter.

BTW, what's the effect for paramcount in call-method-rule?


Julian13 edited on 2004-08-27 16:42

who am i?

reply to topicflat modethreaded modego to previous topicgo to next topicgo to back
  已读帖子
  新的帖子
  被删除的帖子
Jump to the top of page

   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923