java&XML學習第三天,cocoon2
首先,關于cocoon入門的資料網上比較少,一個是ibm上提供的三個cocoon的教程,比較不錯,另外就是cocoon自己的文檔,還有就是必須研究cocoon的源代碼了。
一、cocoon是什么?
按照我的理解,cocoon是一個整套的java web開發框架,象struts里面可以實現的功能,在cocoon里面其實都可以實現,但是,我覺得他的側重點應該是用于在web以各種樣式上發布xml內容(Html,pdf,SVG),他提供了內容、邏輯、表現在很大程度上的分離,這一點不是struts這種MVC框架的強項。
至于說有人將cocoon和struts進行比較,我覺得應該是不恰當的,因為兩者著重解決的問題是不同的,如果你是一個新聞網站,以發布內容為主,那么你可以考慮cocoon,但是如果你是一個信息管理系統,側重于事物的處理,那么你可以選擇struts以及webwork2等框架。
二、cocoon能干什么?
- 提供靜態文件和動態生成的響應
- 使用任意數量的處理將用戶請求透明地映射到物理資源
- 執行簡單和多級 XSLT 轉換
- 將參數動態傳遞到 XSLT 變換
- 生成各種各樣的輸出格式,包括 XML、HTML、PNG、JPEG、SVG 和 PDF
以上是ibm教程上的原話,可能只有最后的一條比較容易理解,不過希望您在讀完本文以后可以對上述的特性都有一個大概的理解。
三、為什么是cocoon 2?
cocoon1和cocoon2是cocoon的兩個不同的版本,其主要的區別是cocoon1是圍繞dom接口開發的,這是一種效率較低的api,而cocoon2是圍繞sax的。所以在學習cocoon2之前,建議了解sax和xml的相關知識。
四、開始進入cocoon 2的世界,管道模型
安裝配置就不說了,網上可以找到相應的說明,而且熟悉java web的人應該可以知道如何安裝。
下面就說一說cocoon 2里面最重要的一個概念:管道
一個管道是由一個輸入開始,一個輸出結束,其中您可以加入任意多的對輸入數據的處理模塊。所以,在cocoon 2中,一個管道應該是1輸入+n處理+1輸出。所有這些模塊,在cocoon中被稱為“components”。
下面是cocoon 2中內置的幾個較為常用的模塊:
管道輸入 — 生成器(如FileGenerator,HTMLGenerator,DirectoryGenerator)和閱讀器(常用來讀靜態文件)
處理步驟 — 轉換器(如XSLT 轉換器)和操作
管道輸出 — 序列化器(如XML,HTML,SVG,PDF序列化器 )
條件的處理 — 匹配器和選擇器
cocoon的管道通常至少有生成器和序列化器,也就是我們說的輸入和輸出。這里面有個感念前面在學習xsl的時候提到過,就是對xml的轉換和格式化輸出是分開的,在cocoon里面很好的體現了這一點。
五、站點地圖
實際上,一個最簡單的管道應該是使用匹配器來接受用戶請求(URL請求),使用生成器生成xml,使用各種轉換器,使用序列化器輸出。所有這些,將體現在cocoon的一個配置文件里面sitemap.xmap,就構成了所謂的“站點地圖”。
下面是我做測試使用的站點地圖:

























































為了節省篇幅,我把后面的東西也放進來,以后會慢慢解釋這個文件,先看圖中的(1),是所有的組件的定義。
(2)就是一個簡單的管道。從他的內容可以看出,首先,他匹配welcome的用戶請求,假使是:http://localhost:8089/cocoon-dev/welcome,然后,有一個生成器,使用的是默認的FileGenerator生成器,這個生成器將會讀取samples.xml文件,把它作為這個管道的輸入。
之后,有一個xsl的轉換器,他使用simple-samples2html.xsl來轉化生成器生成的xml,最后由一個html的序列化器生成輸出。simples.xml和simple-samples2html.xsl的代碼就不給出了,熟悉xml&xslt的朋友應該明白。
在瀏覽器中輸入http://localhost:8089/cocoon-dev/welcome后就會得到輸出的html頁面。當然,如果你將轉換器和序列化器的定義修改成:
<map:transform src="transforms/content2rss.xsl"/>
<map:serialize type="xml"/>
或者
<map:transform src="transforms/content2fo.xsl"/>
<map:serialize type="fo2pdf"/>
的話,你將會得到rss和pdf格式的輸出。個人認為這應該是cocoon的最主要的功能,這也是我了解cocoon的主要原因。
六、使用cocoon進行開發
在cocoon 2的tutorial里面有這樣的一個章節介紹使用cocoon進行web的開發,但是其中只講到了自定義生成器的部分,個人認為cocoon 2的建議是把查詢數據庫,邏輯運算,商業邏輯等功能都放在生成器里面、xsp就是一種生成器他的寫法類似于jsp,但是不管是自定義的生成器還是xsp,其接口都比較復雜,我覺得并沒有struts來的方便,當然這又回到了開始的話題,應用的地方不同,沒有好壞之分,這里只是為了研究一下cocoon2的內部結構。
下面是一個自定義的生成器:











































第二點就是我們的generate方法里面寫的是sax事件的調用,也就是說,在執行generate方法的時候,contentHandler就好像在讀取一個xml文件一樣。為了證明這一點,我們有了管道中(3)的配置。運行http://localhost:8089/cocoon-dev/heyThere之后,我們有了如下結果:


更進一步的說,我們可以這樣理解,generate輸出一個xml,管道的下一個處理器接受到這個xml以后進行一些操作,生成另外一個xml,以此類推,直到序列化器的出現,把xml轉化成了想要的格式。這其實就是cocoon的基本工作原理。
七、實際原理
上面說的工作原理可以通過依次取掉generate后面的處理器,而在最后加裝xml的序列化器來驗證,但是在cocoon的內部,卻沒有什么xml被傳來傳去,那么管道的各個組件之間是怎樣協作的呢?在教程上有句話說是通過互相傳遞sax事件實現的,乍一聽來非常難以理解,經過了無數次調試后,終于得知了實情。
我們來看如下的代碼:




















.......................


.......................






........................







而且,通過調試得知,每一個組件,不管是什么類型,都會有一個XMLConsumer的屬性,另外,還都會有一個contentHandler的屬性。ContentHandler這個類是標準的sax接口,從這一點分析,XMLConsumer有可能是cocoon1的殘留物,而真正在cocoon2里面其作用的是ContentHandler這個接口的一些實現類。
后面又進行了一些調試,結果卻是驗證了上面的說法,為了測試做了如下的配置:
<map:match pattern="welcome">
<map:generate type="helloWorld"/>
<map:transform src="simple-samples2html.xsl"/>
<map:transform src="simple-samples2html2.xsl"/>
<map:serialize type="xml"/>
</map:match>
結果是這樣的,自定義的generate類的generate()方法中的contentHandler.startDocument();一句的實現代碼如下:這段代碼在AbstractXMLPipe這個類中






generate的對象我們稱之為g1,
generate的contentHandler屬性就是TraxTransformer類的一個對象,也就是
<map:transform src="simple-samples2html.xsl"/>這一句的實現載體,我們暫且稱這之對象為t1,
而<map:transform src="simple-samples2html2.xsl"/>的實現載體對象我們暫稱之為t2,
<map:serialize type="xml"/>的實現載體是XMLSerializer類的一個對象,我們暫稱之為s1
他們之間的關系是g1.contentHandler = t1.contentHandler = t2.contentHandler = s1.contentHandler,而且所有的contentHandler都是AbstractXMLPipe這個類的某一個子類型,也就是說他們的startDocument()等方法的實現都是完全一樣的。
這樣一來,每一個sax的事件將會在generate.generate()方法中被開始調用,并不斷地遞歸g1,t1,t2.....s1,這就是cocoon管道之間各個組件互相傳遞數據的真相。
八、其他一些技術的了解:
cocoon中比較有用的一些技術還有xsp和esql,其中xsp是一個類似jsp的組件,他在cocoon中的地位應該是一種generate,用來生成最初的xml,并且,他可以內嵌java代碼,就像jsp那樣,取得request參數,查詢數據庫等,如站點地圖中的(4)所示,我們可以把這樣的一個組件作為管道的起點,這樣我們查詢或者業務處理的結果就可以通過管道被發布成各種樣式了!
下面給出一個xsp的簡單例子:






















esql是在xsp上使用的一項技術,他應該類似于jsp的一些標簽庫,實現的功能是操作數據庫,直接寫在xsp文件中的,這樣可以很方便的生成一個由數據庫驅動的動態的xml,配合上cocoon的其他組件,也就是說可以很方便的把數據庫中的東西發布成各種版本。
下面是他的一些語法定義:
































九、struts&cocoon
目前,已經有人想到了struts和cocoon的整合,用struts來處理邏輯層的事物,用cocoon來實現多種表現形式,操作方法大概提供一個struts的plugin,可以把struts最終的jsp作為cocoon的xml源來使用。
地址:http://struts.sourceforge.net/struts-cocoon/
不過個人認為這種結合的方式還是比較生硬,記得以前看到過關于strutsX的有關介紹,希望這種事物處理層和表現層同樣強大的框架可以早點出來,順便說一句,cocoon 2項目以前是屬于apache xml項目下的,現在已經是一個獨立的項目http://cocoon.apache.org,在這里也祝愿cocoon能夠飛的更高,飛得更遠。
第一次寫那么多,試試發布一下,純粹是可望志同道合的人交流,各位高手見笑了^_^
posted on 2005-03-10 15:38 Boris-Java 閱讀(2179) 評論(2) 編輯 收藏 所屬分類: java&xml