posts - 27,  comments - 37,  trackbacks - 0
          在windows下開(kāi)發(fā)程序,用M$提供的接口處理.ini文件或管理注冊(cè)表的鍵值是非常方便的。在java平臺(tái)上開(kāi)發(fā)程序,則習(xí)慣于以xml格式 的文件來(lái)存放系統(tǒng)的配置信息,對(duì)這種文件的解析和處理,可以用sax或dom。有沒(méi)有更簡(jiǎn)便的方法呢?有,就是用digester模塊。
          Digester是Jakarta 子項(xiàng)目Commons下的一個(gè)模塊,支持基于規(guī)則的對(duì)任意XML文檔的處理。它最初是Structs項(xiàng)目的一部分,后因其通用性而劃歸Commons.

          下載及編譯

          cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
          password: anoncvs
          cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/digester
          cd jakarta-commons/digester
          ant dist

          Digester的運(yùn)行依賴(lài)下列包:
          1. 一個(gè)遵循Jaxp(1.1版本及以后)的XML解析器
          2. Jakarta commons beanutils包(1.5版本及以后)
          3. Jakarta commons collections包(2.1版本及以后)
          4. Jakarta commons logging包(1.0.2版本及以后)

          一個(gè)簡(jiǎn)單的例子

          假定有兩個(gè)JavaBean如下,分別為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);
          }

          用下面的xml文件進(jìn)行配置
          <foo name="The Parent">
             <bar id="123" title="The First Child"/>
             <bar id="456" title="The Second Child"/>
          </foo>

          用下面幾行代碼即可完成配置文件解析工作:
          Digest解析代碼 注釋
          Digester digester = new Digester();
          digester.setValidating(false); 不進(jìn)行XML與相應(yīng)的DTD的合法性驗(yàn)證
          digester.addObjectCreate("foo", "mypackage.Foo"); 當(dāng)遇到<foo>時(shí)創(chuàng)建一個(gè)mypackage.Foo對(duì)象,并將其放在棧頂
          digester.addSetProperties("foo"); 根據(jù)<foo>元素的屬性(attribute),對(duì)剛創(chuàng)建的Foo對(duì)象的屬性(property)進(jìn)行設(shè)置
          digester.addObjectCreate("foo/bar", "mypackage.Bar"); 當(dāng)遇到<foo>的子元素<bar>時(shí)創(chuàng)建一個(gè)mypackage.Bar對(duì)象,并將其放在棧頂。
          digester.addSetProperties("foo/bar"); 根據(jù)<bar>元素的屬性(attribute),對(duì)剛創(chuàng)建的Bar對(duì)象的屬性(property)進(jìn)行設(shè)置
          digester.addSetNext("foo/bar", "addBar", "mypackage.Bar"); 當(dāng)再次遇到<foo>的子元素<bar>時(shí)創(chuàng)建一個(gè)mypackage.Bar對(duì)象,并將其放在棧頂,同時(shí)調(diào)用第二棧頂元素(Foo對(duì)象)的addBar方法。
          Foo foo = (Foo) digester.parse(); 分析結(jié)束后,返回根元素。

          基本情況

          熟悉用SAX來(lái)處理XML文檔的程序員,會(huì)發(fā)現(xiàn)Digester隱藏了遍歷XML元素這些細(xì)節(jié),而是提供了更高一層的、更友好的SAX事件接口,從而讓程序員的精力放在對(duì)數(shù)據(jù)的處理過(guò)程中。
          使用Digester,須按照以下步驟:
          1. 創(chuàng)建一個(gè)org.apache.commons.digester.Digester實(shí)例。一個(gè)解析請(qǐng)求完成后,這個(gè)Digester可以被后面復(fù)用。但也不要試圖在不同的線程中從共享一個(gè)Digester實(shí)例。
          2. 根據(jù)需要設(shè)置一些配置屬性(configuration properties),以控制下一步的解析操作。
          3. 將一個(gè)或幾個(gè)初始對(duì)象(initial object)壓入Digester對(duì)象棧,本步驟不是必須的。
          4. 注冊(cè)所有的元素匹配模板(elemet matching pattern)。當(dāng)一個(gè)模板被從輸入文檔中識(shí)別出來(lái)以后,與其相聯(lián)系的處理規(guī)則(processing rules)被激活。對(duì)一個(gè)特定的模板,可以定義任意多的規(guī)則,當(dāng)識(shí)別出該模板后,這些規(guī)則依序依次執(zhí)行。
          5. 調(diào)用digester.parse()方法,一個(gè)XML文檔的引用(用多種方式供選擇)要傳給這個(gè)方法。注意,需要捕捉并處理IOException或SAXEception或處理過(guò)程中拋出的異常。

          元素匹配模板

          Digester能自動(dòng)遍歷目標(biāo)XML文檔的元素形成的層次結(jié)構(gòu),這個(gè)過(guò)程無(wú)需程序員參與。程序員的任務(wù)是決定,在解析的過(guò)程中,當(dāng)由嵌套的元素形成的一個(gè)特定序列被識(shí)別出時(shí),如何處理它。用以描述這種序列的機(jī)制,就叫“元素匹配模板”。
          具體說(shuō)來(lái),元素和其子元素間,用”/”相隔,如果一些元素前沒(méi)有”/”則其必為根元素。如例:
          <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>

          字符”*”表示任意級(jí)別,如”*/a”表示任意級(jí)別的<a>都可匹配(不包括根元素級(jí)的).熟悉XLST的朋友,對(duì)這種思路一定不陌生。
          從上面的描述,可知某個(gè)元素同時(shí)滿(mǎn)足多個(gè)匹配模板是非??赡艿?,在這種情況下,與各個(gè)模板相關(guān)聯(lián)的處理規(guī)則(processing rule)的執(zhí)行順序如下:對(duì)begin或body方法,按照各個(gè)rule的注冊(cè)順序的先后,對(duì)end方法則是注冊(cè)順序的反序。

          處理規(guī)則(processing rule)

          元素匹配模板用以識(shí)別什么時(shí)候采取行動(dòng),處理規(guī)則則用以定義行動(dòng)的內(nèi)容。
          從形式上講,一個(gè)處理規(guī)則是一個(gè)java類(lèi),它擴(kuò)展了org.apache.commons.digester.Rule類(lèi)。每個(gè)處理規(guī)則,實(shí)現(xiàn)下列 的一個(gè)或幾個(gè)事件處理方法(event method),當(dāng)相應(yīng)的模板匹配成功以后,在已定義的某個(gè)時(shí)刻,這些事件方法會(huì)被觸發(fā)。
          1. begin(),在一個(gè)匹配元素被識(shí)別出后的“開(kāi)始”時(shí)刻被調(diào)用,這個(gè)元素的所有屬性放在一個(gè)數(shù)據(jù)結(jié)構(gòu)中被傳遞給begin()
          2. body(),當(dāng)元素的嵌套內(nèi)容(如子元素)被識(shí)別出時(shí)被調(diào)用。在解析的過(guò)程中,前后的空白被去掉了
          3. end(),匹配元素的“結(jié)束”時(shí)刻被調(diào)用。如果子元素也匹配相關(guān)的規(guī)則,則這些規(guī)則的方法需都執(zhí)行畢,才能達(dá)到該元素的“結(jié)束”時(shí)刻。
          4. finish(),解析結(jié)束時(shí)被調(diào)用,以提供給各個(gè)規(guī)則以清理臨時(shí)數(shù)據(jù)的機(jī)會(huì)。

          在設(shè)置digester時(shí),通過(guò)調(diào)用addRule()方法,來(lái)注冊(cè)一個(gè)特定的元素匹配模板以及相應(yīng)的一個(gè)Rule類(lèi)的實(shí)例。如上所述,Rule類(lèi)中的事件處理方法,會(huì)在適當(dāng)?shù)臅r(shí)間被調(diào)用。這個(gè)機(jī)制,允許動(dòng)態(tài)地生成Rule的實(shí)現(xiàn)。
          另外,digester也提供了一些處理常見(jiàn)情況的處理規(guī)則類(lèi)。
          1. ObjectCreateRule,當(dāng)begin()方法被調(diào)用時(shí),這個(gè)規(guī)則類(lèi)實(shí)例化一個(gè)指定的java類(lèi),并將其壓入棧頂。這個(gè)被實(shí)例 化的類(lèi)的名字,默認(rèn)是這個(gè)規(guī)則類(lèi)構(gòu)造函數(shù)得到的參數(shù),也可以通過(guò)指定正在處理的xml元素的屬性來(lái)傳遞一個(gè)新的類(lèi)的名字。當(dāng)end()方法被調(diào)用 時(shí),棧 頂?shù)膶?duì)象被彈出,Digester中對(duì)它的任何引用將被忽略。
          2. FactoryCreateRule,一個(gè)非常有用的ObjectCreateRule的變體。
          3. SetPropertiesRule,當(dāng)begin()方法被調(diào)用時(shí),digester使用標(biāo)準(zhǔn)的Java Relection API來(lái)識(shí)別JavaBean的屬性設(shè)置方法(setter method),這些方法名稱(chēng)中包含屬性(property)的名字,這些屬性與XML元素的屬性(attribute)匹配,于是這些方法被調(diào)用并將相 應(yīng)的屬性值(attribute value)傳給它們。這些自然的映射可以被重寫(xiě)。建議不要過(guò)度使用這項(xiàng)功能,在大多數(shù)情況下,使用標(biāo)準(zhǔn)的BeanInfo機(jī)制會(huì)更好。
          4. SetPropertyRule,當(dāng)begin()方法被調(diào)用時(shí),digester調(diào)用棧頂對(duì)象的一個(gè)特定的屬性設(shè)置方法(property setter)并傳給它特定的值(property和值分別由兩個(gè)attribute命名)。這對(duì)XML需要遵循一個(gè)指定的DTD時(shí)比較有用,你可以設(shè)置 一個(gè)特別的屬性(property),雖然在指定DTD沒(méi)有attribute與其相對(duì)應(yīng)。
          5. SetNextRule,當(dāng)end()方法被調(diào)用時(shí),digester分析第二棧頂元素,尋找一個(gè)特定屬性(property)的設(shè)置方法 (setter method),并接著調(diào)用這個(gè)方法,以棧頂?shù)脑刈鲄?shù)。這個(gè)規(guī)則通常用來(lái)在兩個(gè)對(duì)象間建立1對(duì)多的關(guān)系,所用的方法也常被叫做addChild什么 的。
          6. SetTopRule,當(dāng)end()方法被調(diào)用時(shí),digester分析棧頂元素,尋找一個(gè)特定屬性(property)的設(shè)置方法 (setter method),并接著調(diào)用這個(gè)方法,以第二棧頂?shù)脑刈鲄?shù)。這個(gè)規(guī)則通常用來(lái)在兩個(gè)對(duì)象間建立1對(duì)多的關(guān)系,所用的方法也常被叫做setParent 什么的。
          7. CallMethodRule,這個(gè)規(guī)則設(shè)置當(dāng)end()被調(diào)用時(shí)執(zhí)行的棧頂對(duì)象的自定義方法,通過(guò)對(duì)這個(gè)規(guī)則的設(shè)置,來(lái)指定方法的名字、參數(shù)的數(shù)量以及定義的參數(shù)類(lèi)型的Java類(lèi)的名字。實(shí)際的參數(shù)值,來(lái)自激活這個(gè)方法的元素的子元素。
          8. CallParamRule,這個(gè)規(guī)則用來(lái)指定CallMethodRule的參數(shù)的值的來(lái)源,它可以來(lái)自一個(gè)特定的屬性,或子元素的body的內(nèi)容.
          9. NodeCreateRule,一個(gè)特殊的規(guī)則,將對(duì)象樹(shù)的一部分轉(zhuǎn)換成一個(gè)DOM結(jié)點(diǎn)(Node),并壓入棧頂。

          對(duì)這些標(biāo)準(zhǔn)的規(guī)則類(lèi),可以創(chuàng)建它們的實(shí)例,并調(diào)用digester.addRule來(lái)注冊(cè)它們。由于經(jīng)常使用它們,所以digester定義了一些簡(jiǎn)便的方法來(lái)注冊(cè)它們。如:
          Rule rule = new SetNextRule(digester, "addChild","com.mycompany.mypackage.MyChildClass");
          digester.addRule("a/b/c", rule);
          可以用下列代碼替換digester.addSetNext("a/b/c", "addChild", "com.mycompany.mypackage.MyChildClass");


          原文章鏈接: 竹筍炒肉



           小時(shí)候家的對(duì)面有一座山,山的上面就是藍(lán)天,所以總是幻想著有一天站到山頂用手摸一下藍(lán)天……
          posted on 2007-11-04 16:34 丫丫 閱讀(253) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2007年11月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          常用鏈接

          留言簿(1)

          隨筆分類(lèi)(25)

          隨筆檔案(27)

          文章分類(lèi)

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 九龙城区| 崇文区| 当阳市| 汉沽区| 上林县| 那曲县| 米泉市| 刚察县| 吴忠市| 米脂县| 河北区| 达州市| 沙坪坝区| 沈丘县| 侯马市| 奉节县| 固镇县| 敦煌市| 安庆市| 田林县| 辽宁省| 鄱阳县| 凤庆县| 张家口市| 乐平市| 民勤县| 融水| 甘南县| 仙桃市| 东乌| 灯塔市| 栖霞市| 鸡西市| 佳木斯市| 大洼县| 河西区| 兴义市| 宜黄县| 壶关县| 祥云县| 涡阳县|