一、什么是cocoon,它能做什么
Cocoon 是一種 Java 服務器框架,它允許使用 XSLT(XML 樣式表語言轉換 (XML Stylesheet Language-Transformation))轉換動態(tài)發(fā)布 XML 內容。通過依靠 XML 描述內容以及使用 XSLT 將內容轉換成多種格式,Cocoon 提供了用于構建內容、邏輯和表示在很大程度上彼此分離的應用程序的平臺。
Cocoon 使用管道的概念來描述將內容發(fā)布到 Web 的過程。管道由一些輸入數(shù)據(jù)以及隨后對它進行的一些處理步驟構成。每個處理步驟接受前一步的輸出作為輸入,一直到達管道的末端并產生最終輸出。它包含各種各樣的可重用組件,這些組件可以配置成使用最低限度的 Java 開發(fā)生成復雜的行為。例如,通過單獨使用 XML 和 XSLT,Cocoon 可用于:
- 提供靜態(tài)文件和動態(tài)生成的響應
- 使用任意數(shù)量的處理將用戶請求透明地映射到物理資源
- 執(zhí)行簡單和多級 XSLT 轉換
- 將參數(shù)動態(tài)傳遞到 XSLT 變換
- 生成各種各樣的輸出格式,包括 XML、HTML、PNG、JPEG、SVG 和 PDF
二、Cocoon 2 體系結構的原理
首先,處理 XML 文檔可分成幾個離散的步驟。這些步驟的組合描述處理管道。管道由輸入、某些處理以及輸出構成。Cocoon 2 使用 SAX 事件作為每個處理步驟之間的連接。
第二,可以使用特殊類型的組件來對管道中的每個階段建模。例如,用生成器生成輸入,用序列化器生成輸出。
第三,對用戶請求的響應包括確定為請求(與其輸入一起)服務的正確管道,然后指示管道執(zhí)行其處理以生成給用戶的響應。
2.1管道組件
Cocoon 包含許多常規(guī)管道組件,可以用有用的方法將它們連接起來。根據(jù)這些組件在管道中扮演的角色,可以將它們分組成幾種完全不同的類型。
- 管道輸入 — 生成器和閱讀器
- 處理步驟 — 轉換器和操作
- 管道輸出 — 序列化器
- 條件的處理 — 匹配器和選擇器
Cocoon 管道通常至少由生成器和序列化器組成,但可能含有任意數(shù)量的處理步驟。將數(shù)據(jù)作為 SAX 事件通過 Cocoon 管道傳遞。
2.1.1輸入-生成器和閱讀器:
生成器負責讀取數(shù)據(jù)源(例如,文件),然后將該數(shù)據(jù)作為一系列 SAX 事件傳遞到管道。因此,最簡單的生成器是 SAX 解析器。通常,任何可以被映像成一系列 SAX 事件的數(shù)據(jù)源都可以成為生成器的基礎。
在 Cocoon 中有許多可用的生成器。最有用的是:
- FileGenerator:從文件系統(tǒng)或 Web 讀取 XML 文件
- HTMLGenerator: 從文件系統(tǒng)或 Web 讀取 HTML 文件
- DirectoryGenerator:讀取文件系統(tǒng)以提供目錄清單
閱讀器是 Cocoon 管道模型中的特例,因為它們不是理解 XML 的組件。閱讀器只是訪問外部資源,然后將它直接復制到響應。通常使用它們來提供靜態(tài)文件(例如,圖像或 CSS 樣式表)。可以將閱讀器視為自包含的管道;它們生成輸入數(shù)據(jù),然后將數(shù)據(jù)序列化成響應。
2.1.2處理-轉換器和操作
轉換器是 Cocoon 管道中的主要處理步驟。它們接受 SAX 事件作為輸入,執(zhí)行一些有用的處理,然后將結果作為 SAX 事件傳入管道。一種查看轉換器的有用方法是作為在 SAX 事件流通過它時修改 SAX 事件流的組件。在這一點上,它們類似于 SAX 過濾器。
使用最廣泛的轉換器是 XSLT 轉換器。它將其輸入傳遞到執(zhí)行 XSLT 轉換的 XSLT 處理器中。然后將轉換的結果作為 SAX 事件反饋到管道。
操作是將附加動態(tài)行為插入管道的一種方法,并且通常為特殊應用程序定制。但是,某些一般的操作與 Cocoon 捆在一起,例如,執(zhí)行數(shù)據(jù)庫交互,表單驗證和發(fā)送郵件等。操作的成功完成還會影響是否執(zhí)行后續(xù)處理步驟。
2.1.3 輸出:序列化器
序列化器是 Cocoon 管道中的端點。它們負責接收直接從生成器(在可能最短的管道中)或者以前的處理步驟(例如轉換器)產生的 SAX 事件流,然后將它們解釋成適合于響應的格式。特定格式取決于正在使用的確切序列化器。
最簡單的序列化器是 XML 序列化器,它只是將 SAX 事件轉換回 XML 文檔。其它序列化器可以生成 HTML、純文本、PDF 文檔甚至圖像。所有這些序列化器都期望 SAX 事件流符合一個特殊的 XML 詞匯表:
- HTML 序列化器:將 XHTML 轉換成有效的 HTML
- SVG 序列化器:將 SVG 轉換成 JPEG 或 PNG 圖像
- PDF 序列化器:將 XSL-FO 轉換成 PDF 文檔
接受 XML 內容、對它進行處理,然后為其提供多種格式的能力是 Cocoon 框架的真正力量所在。
2.1.4條件:匹配器和選擇器
任何特殊管道可能涉及某些條件節(jié)。例如,確切的處理步驟可能取決于請求參數(shù)、用戶瀏覽器等之類的因素。
匹配器是兩個條件組件中最簡單的部分,等價于簡單的 if
語句。如果某個條件為真,則對特殊管道或者管道的一節(jié)進行求值。
第二種條件組件是選擇器,它與 if-then-else
語句類似。當幾個選項之一可用時使用選擇器,它通常用于在管道中創(chuàng)建條件節(jié),而匹配器則用于測試是否應該進入一個特殊管道。
這些組件中的每一個都有幾種實現(xiàn)。它們都遵循測試請求某些方面(例如,主機名、用戶代理、參數(shù)或 URL)或用戶會話的公共模式。可以使用通配符或正則表達式來完成匹配,而通常選擇器枚舉所有可能的值。
2.2讓管道工作
對接收請求和為響應提供服務的邏輯周期的描述可以歸納如下:
對接收請求和為響應提供服務的邏輯周期的描述可以歸納如下:
- 從用戶接受請求。
- 確定用來解釋該請求并生成響應的適當管道(使用匹配器)。
- 從可用的預配置的組件構造管道。
- 指示管道為請求服務。
- 將由管道生成的響應返回用戶,可能對結果進行高速緩存以便以后使用。
這是 Cocoon 用來將 XML 發(fā)布到 Web 的基本請求-響應周期。要管理這一周期,Cocoon 提供了一個稱為 sitemap 的 XML 配置文件。
三、安裝和配置cocoon
將 Cocoon 部署到 Tomcat 中很簡單,只需將 cocoon.war
復制到 $CATALINA_HOME/ webapps
目錄中,然后重新啟動 Tomcat。
除了sitemap,Cocoon 只有兩個配置文件。可以在 $CATALINA_HOME/webapps/cocoon/WEB-INF
中找到它們:
log.xconf:配置 Cocoon 日志記錄。Cocoon 將 Apache Log4J 用于內部日志記錄(請參閱參考資料)。缺省情況下,Cocoon 將日志文件寫入 $CATALINA_HOME\webapps\cocoon\WEB-INF\logs
。
cocoon.xconf:配置 Cocoon 高速緩存、數(shù)據(jù)源和許多其它高級選項。
出于開發(fā)目的,在 cocoon.xconf
中進行一處更改是很有幫助的。找到下列項:<sitemap file="sitemap.xmap" reload-method="asynchron" check-reload="yes" logger="sitemap"/>
現(xiàn)在,將 reload-method
屬性的值更改為 synchron
。這改變了 Cocoon 如何對網站地圖的更改作出響應,網站地圖是配置 Cocoon 應用程序的中心位置。將行為更改為 synchon
意味著 Cocoon 將在對任何請求提供服務之前立即作用于更改。缺省異步行為意味著它將在后臺讀取更改,因此它們將不會馬上顯示出來。在開發(fā)期間,當立即結果是更可取的,但是對于必須繼續(xù)盡可能快的為用戶服務的活動應用程序來說并不是最理想的時候,這可能令人沮喪。
四、網站地圖
網站地圖是管理 Cocoon 網站的中心位置,它完成兩個功能:
- 它是在管道中使用組件之前聲明它們的位置。
- 它是使用聲明的組件來定義管道的位置。
下面是一個帶說明的比較完整的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<map:sitemap
xmlns:map="http://apache.org/cocoon/sitemap/1.0">
<map:components>
<map:generators default="file">
<map:generator name="file" src="org.apache.cocoon.generation.FileGenerator"/>
<map:generator name="csv" src="com.mycompany.CSVGenerator"/>
</map:generators>
<map:transformers default="xslt">
<map:transformer name="xslt" src="org.apache.cocoon.transformation.TraxTransformer"/>
<map:transform src="transforms/content2rss.xsl"/>
<map:transform src="transforms/content2svg.xsl"/>
<map:transform src="transforms/content2fo.xsl"/>
<!--Cocoon 支持從網站地圖中傳遞參數(shù)。第一種方法是使用 map:parameter 元素來完成該任務。
參數(shù)的 name 和 value 都被指定成 map:parameter 元素的屬性。
使用這一方法將固定的和動態(tài)的參數(shù)都傳遞到樣式表中是有可能的。
第二個參數(shù)元素的值將由匹配模式中的第一個通配符設置。
只要樣式表包含 xsl:param 元素,參數(shù)就能正確地被傳遞到轉換。-->
<map:transform src="transforms/content2html.xsl">
<map:parameter name="myFixedParam" value="fixed-value"/>
<map:parameter name="myDynamicParam" value="{1}"/>
</map:transform>
<!--另一種將參數(shù)傳遞到樣式表的方法允許傳遞所有 URL 請求參數(shù)。例如,如果對
http://localhost:8080/content.html?param1=value1¶m2=value2 的請求導致觸發(fā)這個管道,
則兩個參數(shù)(param1 和 param2)將被傳遞到樣式表。 -->
<map:transform src="transforms/content2html.xsl">
<map:parameter name="use-request-parameters" value="true"/>
</map:transform>
<!--
當請求中可能被傳遞的參數(shù)個數(shù)是可變時,這一方法很有用。但是,這是以犧牲一點性能為代價的,因為 Cocoon 對使用這一方法的轉換的結果進行高速緩存的能力低于那些使用固定參數(shù)的轉換。如果任何 URL 參數(shù)改變了,即使不由樣式表直接使用,也不會使用高速緩存的結果。-->
</map:transformers>
<map:readers default="resource">
<map:reader name="resource" src="org.apache.cocoon.reading.ResourceReader"/>
</map:readers>
<map:serializers default="html">
<map:serialize type="xml"/>
<map:serializer name="xml" mime-type="text/xml" src="org.apache.cocoon.serialization.XMLSerializer"/>
<map:serializer name="html" mime-type="text/html" src="org.apache.cocoon.serialization.HTMLSerializer"/>
<map:serializer name="svg2png" src="org.apache.cocoon.serialization.SVGSerializer" mime-type="image/png"/>
<map:serializer name="fo2pdf" src="org.apache.cocoon.serialization.FOPSerializer" mime-type="application/pdf"/>
</map:serializers>
<map:matchers default="wildcard">
<map:matcher name="wildcard" src="org.apache.cocoon.matching.WildcardURIMatcher"/>
</map:matchers>
</map:components>
<map:pipelines>
<map:pipeline>
<map:match pattern="index.html">
<map:read src="static/index.html" mime-type="text/html"/>
</map:match>
</map:pipeline>
<map:pipelines>
<map:pipeline>
<map:match pattern="*.css">
<map:read src="styles/{1}.css" mime-type="text/css"/>
</map:match>
<map:match pattern="**.html">
<map:read src="static/{1}.html" mime-type="text/html"/>
</map:match>
</map:pipeline>
<!--
單一星號與任意數(shù)目的字符匹配,除了正斜杠
雙星號與包括正斜杠之外的任意數(shù)目字符匹配
index.html 的匹配模式應該在 *.html 之前聲明,否則,它將永遠不會被匹配。
-->
<!--
首先,聲明管道以及用來觸發(fā)它的匹配模式:
-->
<map:pipe>
<map:match pattern="content/*.html">
<!--下一步,添加一個生成器以從 content 目錄中讀取 XML 文檔:-->
<map:generate src="content/{1}.xml"/>
<!--下一步,添加一個轉換器來通過使用特定樣式表轉換 XML 文檔:-->
<map:transform src="transforms/content2html.xsl"/>
<!--最后,使用一個序列化器將轉換結果變成返回給用戶的 HTML 文檔:-->
<map:serialize type="html"/>
</map:match>
</map:pipe>
<!--
請求 URL http://localhost:8080/content/document.html 觸發(fā)這一管道并使 Cocoon 首先對 document.xml 進行解析,然后在將結果傳回瀏覽器之前使用 $COCOON_HOME/transforms/content2html.xsl 來轉換它。
-->
</map:sitemap>