common digester-入門


Commons-Digester簡介




一.歷史

Digester原本僅僅是Jakarta Struts中的一個工具,用於處理struts-config.xml配置文件。顯然,將XML文件轉換成相應的Java對象是一項很通用的功能,這個工具理應具備更普遍的用途,因此很快它就在Jakarta Commons項目(用於提供可重用的Java組件庫)中有了一席之地。java



二.幾個要點

簡言之,Digester由"事件"驅動,經過調用預約義的規則操做對象棧,將XML文件轉換爲Java對象。工做原理以下:數據庫

Digester底層採用SAX解析XML文件,因此很天然的,對象轉換由"事件"驅動,即在識別出特定XML元素時(實際被細分爲begin、body、end、finish四個時點),將執行特定的動做,好比建立特定的Java對象,或調用特定對象的方法等。此處的XML元素根據匹配模式(matching pattern)識別,而相關操做由規則(rule)定義。在轉換過程當中,Digester維持了一個對象棧,能夠看做對象轉換的工做臺,用來存放轉換中生成的、或是爲轉換臨時建立的Java對象。對輸入XML文件做了一趟完整的掃描後,對象棧的棧頂元素即爲目標對象。因爲Digester屏蔽了SAX解析的細節,使用者僅需關注轉換操做自己,大大簡化了轉換操做。apache


對使用者而言,Digester的核心在於匹配模式與規則(matching pattern + rule)。編程


匹配規則示例以下:
   <a>          -- Matches pattern "a"
     <b>        -- Matches pattern "a/b"
       <c/>     -- Matches pattern "a/b/c"
       <c/>     -- Matches pattern "a/b/c"
     </b>
     <b>        -- Matches pattern "a/b"
       <c/>     -- Matches pattern "a/b/c"
       <c/>     -- Matches pattern "a/b/c"
       <c/>     -- Matches pattern "a/b/c"
     </b>
   </a>函數


Digester提供了一些編程中常常用到的規則(rule),如下五類九個rule較爲經常使用:工具

A:對象建立
1.ObjectCreateRule   當begin()方法被調用時, 此rule建立相應Java對象, 並將其push到Digester的對象棧上。當end()方法被調用時, 棧頂對象將被pop, Digester內全部對該對象的引用都將失效。
2.FactoryCreateRule     建立Java對象的另外一種選擇。當待建立的Java對象沒有無參構造函數,或須要在建立時須要進行額外的設置時,須要用此rule。測試


B:屬性設置
3.SetPropertiesRule     當begin()方法被調用時, Digester使用標準的Java反射API,將棧頂對象的屬性設置爲XML元素的同名屬性值。
4.SetPropertyRule     當begin()方法被調用時, Digester調用棧頂對象某指定屬性的設置方法,設置其值。this


C:父子關係管理
5.SetNextRule     當end()方法被調用時, Digester將棧頂元素設置進次棧頂元素中(調用相應的設置方法)。
6.SetTopRule     當end()方法被調用時, Digester將次棧頂元素設置進棧頂元素中(調用相應的設置方法)。編碼


D:任意方法調用
7.CallMethodRule     當end()方法被調用時, Digester將調用棧頂元素指定名稱的方法。除了方法名外,此rule還須要配置參數數目,參數類型。參數值通常經過CallParamRule獲得。
8.CallParamRule     此rule內嵌於CallParamRule中,按順序(相對於0)定義了CallParamRule中參數值的來源,可選的來源包括當前XML元素的屬性或內容。spa


E:其它
9.NodeCreateRule     將XML文件樹的一部分轉換爲DOM節點,並push到Digester的對象棧上。


在基本使用中,使用者經過調用Digester類的相關方法,來建立匹配模式與規則的映射序列。好比,調用addSetProperties(String pattern),向Digester中加入SetPropertiesRule。




三.如何使用?

基本步驟以下:
1.建立Digester對象實例。
2.設置該Digester對象的配置屬性(可選)。
3.將須要的初始對象push到該Digester對象的對象棧上(可選)。
4.須要註冊全部的XML元素匹配模式與處理規則之間的映射關係。
5.用digester.parse()解析的XML文檔對象,獲得目標對象。



下面是一個簡單示例:
1.foo.xml   數據源文件
2.Foo.java   目標Java對象
3.Bar.java   目標Java對象
4.Entry.java   調用Digester的入口類

【foo.xml】
<?xml version="1.0" encoding="GBK"?>
<foo name="The Parent">
     <bar id="123" title="The First Child"/>
     <bar id="456" title="The Second Child"/>
</foo>

【Foo.java】
package org.easev.digester;

import java.util.HashMap;
import java.util.Iterator;

public class Foo {

     private String name;

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

     public String getName() {
         return name;
     }

     private HashMap bars = new HashMap();

     public void addBar(Bar bar) {
         bars.put(String.valueOf(bar.getId()), bar);
     }

     public Bar findBar(int id) {
         return (Bar) bars.get(String.valueOf(id));
     }

     public Iterator getBars() {
         return bars.keySet().iterator();
     }
}

【Bar.java】
package org.easev.digester;

public class Bar {

     private int id;

     public int getId() {
         return id;
     }

     public void setId(int id) {
         this.id = id;
     }

     private String title;

     public String getTitle() {
         return title;
     }

     public void setTitle(String title) {
         this.title = title;
     }
}

【Entry.java】
package org.easev.digester;

import java.io.File;
import java.util.Iterator;

import org.apache.commons.digester.Digester;

public class Entry {

     public static void main(String[] args) throws Exception {
         //相對路徑定義與包名相關
         File input = new File("org/easev/digester/foo.xml");
         Digester digester = new Digester();
         digester.setValidating(false);

         //完整類名定義,包名改變時需作相應變化
         digester.addObjectCreate("foo", "org.easev.digester.Foo");
         digester.addSetProperties("foo");
         digester.addObjectCreate("foo/bar", "org.easev.digester.Bar");
         digester.addSetProperties("foo/bar");
         digester.addSetNext("foo/bar", "addBar", "org.easev.digester.Bar");

         Foo foo = (Foo) digester.parse(input);

         //測試裝載是否成功
         Iterator iter = foo.getBars();
         while (iter.hasNext()) {
             System.out.println((String) iter.next());
         }
     }

}

匹配模式沒有什麼文章好作,那麼下面要討論的就必然是規則了。在基本的使用方式下,Digester雖然使用XML文件定義Java對象的狀態,提升了系統的靈活性,可是匹配模式與規則的映射序列(裝載邏輯)仍然經過硬編碼來定義,這種方式不易修改與重用。因此Digester還提供了一種高級的使用方式,用一個XML文件定義Java對象的狀態(數據源文件),用另外一個XML文件定義裝載數據源文件的裝載邏輯。


這樣,對象的裝載過程分紅了兩步:
1.裝載邏輯的"裝載",其結果表現爲定義了rule的Digester;
2.根據上一步獲得的Digester,裝載目標對象。

套用上面的一個例子,增長了rule.xml,並改寫了Entry.java

【rule.xml】
<?xml version='1.0'?>
<!DOCTYPE digester-rules 
   PUBLIC "-//Jakarta Apache //DTD digester-rules XML V1.0//EN" 
     "">

<digester-rules>
   <pattern value="foo">
     <object-create-rule classname="org.easev.digester.Foo"/>
     <set-properties-rule/>
     <pattern value="bar">
       <object-create-rule classname="org.easev.digester.Bar"/>
       <set-properties-rule/>
       <set-next-rule methodname="addBar"/>
     </pattern>
   </pattern>
</digester-rules>

【Entry.java】
package org.easev.digester;

import java.io.File;
import java.util.Iterator;

import org.apache.commons.digester.Digester;

public class Entry {

     public static void main(String[] args) throws Exception {
         //相對路徑定義與包名相關
         File data = new File("org/easev/digester/foo.xml");
         File rule = new File("org/easev/digester/rule.xml");
         Digester digester = DigesterLoader.createDigester(rule.toURL());
         Foo foo = (Foo) digester.parse(data);
        
         //測試裝載是否成功
         Iterator iter = foo.getBars();
         while (iter.hasNext()) {
             System.out.println((String) iter.next());
         }
     }

}

咱們能夠看到,使用Digester的代碼變得至關簡潔,而要付出的代價就是爲裝載邏輯寫一個配置文件。



四.其餘的替代技術

除了Digester以外,固然還有其它的方法來實現Java對象的綁定與裝載:1.java.util.Properties,簡單的配置屬性(好比數據庫鏈接信息),能夠寫在properties文件中,調用Properties對象的load(InputStream)方法將配置中的健值對加載到Properties對象中。這種方式通常僅適用於簡單的配置信息的加載。2.JAXB,Java Architecture for XML Binding,在Java Web Services Developer Pack V 1.1中提供了一個參考實現。使用這種方式時,除了提供數據源XML文件以外,還必須提供相應的Schema文件。加載前,首先用Binding Compiler將Schema轉換獲得目標Java類的接口與實現,而後再調用Unmarshaller或Marshaller將數據源XML文件信息加載到Java對象中,或將設置的Java對象數據導出爲XML文件。 3.XPath 4.JaxMe

相關文章
相關標籤/搜索