Digester 是一個依據 xml 配置文件動態構建 Java 對象樹的工具,基於 SAX 解析器進行封裝,它爲 SAX 事件的處理提供了更高級和友好的接口,讓開發更專一於要執行的處理,隱藏了 XML 元素詳細的層次結構信息。java
爲了便於實現,內部使用堆棧存儲建立的對象。當知足元素匹配模式時,按預設的處理規則操做棧中對象。編程
典型的建立對象處理邏輯是,觸發建立新對象的規則,在遇到特定 XML 元素的開頭時將其推送到棧頂;處理此元素的嵌套內容和屬性時,該對象將保留在堆中;當遇到元素的末尾時,將它彈出。緩存
Digester 提供的處理規則解決了這種設計的幾個潛在問題:微信
Digester 解析器的一個主要特性是自動肯定正在解析的 XML 文檔的元素層次結構,開發人員只需在解析過程當中遇到某種嵌套元素排列時,決定要執行哪些函數。元素匹配模式,確認的就是執行函數也就是規則。數據結構
一個很是簡單的元素匹配模式是一個簡單的字符串,如"a"。只要在 XML文檔中遇到頂級元素 <a>,不管它發生多少次,都會匹配此模式。請注意,嵌套的 <a> 元素將不匹配此模式。框架
比較複雜的是匹配嵌套元素,如 "a/b",當找到嵌套在頂級 <a> 元素內的 <b> 元素時,將匹配此模式。一樣,這種匹配能夠根據須要屢次發生,具體取決於要解析的XML文檔的內容。也可使用多個斜槓來定義要匹配的任何所需深度的層次結構。函數
例如,假設已註冊與 "a", "a/b", 和 "a/b/c" 模式匹配的處理規則。對於具備如下內容的輸入XML文檔,在解析相應元素時將匹配指示的模式:工具
<a> -- 匹配 "a"
<b> -- 匹配 "a/b"
<c/> -- 匹配 "a/b/c"
<c/> -- 匹配 "a/b/c"
</b>
<b> -- 匹配 "a/b"
<c/> -- 匹配 "a/b/c"
<c/> -- 匹配 "a/b/c"
<c/> -- 匹配 "a/b/c"
</b>
</a>
複製代碼
經過在匹配的模式字符串中使用 "*" 通配符,也能夠匹配特定的XML元素,不管它是如何嵌套(或不嵌套)在XML文檔中。例如,元素匹配模式 "*/a" 將匹配文檔內任何嵌套位置的元素 <a>。源碼分析
若是一個匹配模式對應多個處理規則,將按順序觸發。 begin(和body)方法按照最初向 Digester 註冊的 Rules 的順序執行,而 end 方法調用以相反的順序執行。 換句話說 - 順序是先進先出的。spa
處理規則定義的時模式匹配時應該發生的動做,它一般時 Rule 接口的子類,每一個規則實現瞭如下一個或多個事件方法,這些方法會在解析的過程當中執行:
Digester 提供了一組處理規則實現類,用於處理許多常見的編程場景,這些類分別是:
假設有兩個簡單的 JavaBeans,Foo 和 Bar,方法簽名以下:
package mypackage;
public class Foo {
public void addBar(Bar bar);
public Bar findBar(int id);
public Iterator getBars();
public String getName();
public void setName(String name);
}
public mypackage;
public class Bar {
public int getId();
public void setId(int id);
public String getTitle();
public void setTitle(String title);
}
複製代碼
而且使用 Digester 來解析如下 XML 文檔:
<foo name="The Parent">
<bar id="123" title="The First Child"/>
<bar id="456" title="The Second Child"/>
</foo>
複製代碼
一個簡單的方法是使用 Digester 設置以下方式的解析規則,而後處理包含此文檔的輸入文件:
Digester digester = new Digester();
digester.setValidating(false);
digester.addObjectCreate("foo", "mypackage.Foo");
digester.addSetProperties("foo");
digester.addObjectCreate("foo/bar", "mypackage.Bar");
digester.addSetProperties("foo/bar");
digester.addSetNext("foo/bar", "addBar", "mypackage.Bar");
Foo foo = (Foo) digester.parse();
複製代碼
這些規則將按順序執行如下任務:
解析完成後,第一個被推入堆棧的對象(本例中爲 Foo 對象)將返回,它的屬性已被初始化,幷包含建立的全部子 Bar 對象。
每一個框架都有本身解析 XML 的方法,Tomcat 也不例外,本文對 Digester 的基本原理進行了總結,使用仍是比較簡單方便的。
此外,Digester 還有一些其餘設置,好比指定建立對象使用的類加載器,是否以命名空間的方式解析,是否根據指定的 DTD 驗證文檔,還有 RuleSet 可重用規則集的使用等。
搜索微信公衆號「頓悟源碼」,獲取更多源碼分析和造的輪子。