XML Server Pages(XSP) 筆記
1、基本概念
XSP可以將動態(tài)數(shù)據(jù)添加到XML 文檔中以創(chuàng)建更豐富的網(wǎng)站,也可以使 Cocoon 2 集成現(xiàn)有數(shù)據(jù)源和/或 API 以在因特網(wǎng)上用多種格式發(fā)布數(shù)據(jù)。它是一種能夠創(chuàng)建動態(tài) XML 數(shù)據(jù)源以便將數(shù)據(jù)傳輸?shù)?Cocoon 2 管道的 Cocoon 2 技術(shù)。通過使用 XML 標記和應用邏輯的組合來描述這些數(shù)據(jù)源,然后由 Cocoon 2 引擎自動將這種組合編譯為 Java 類。XSP 為使用 Cocoon 2 開發(fā)應用程序提供了一個靈活的平臺。例如,Cocoon 2 應用程序可以顯示現(xiàn)有應用程序數(shù)據(jù)庫中的信息,而且啟用了更為多樣的數(shù)據(jù)發(fā)送選項。通過提供一種通過 XML 界面顯示數(shù)據(jù)源的方法,XSP 允許在諸如中間件和文檔發(fā)布那樣的應用程序集成環(huán)境中使用 Cocoon 2。
1.1 XSP 與 JSP
1.1.1相同點:
1)由程序代碼和標記的混合體組成
2)被編譯成用于執(zhí)行的二進制形式
3)允許創(chuàng)建定制標記庫
1.1.2不同點:
1) XSP 為將任何編程語言中的代碼與 XML 標記混合在一起提供了一個框架。
2) XSP 生成動態(tài)數(shù)據(jù)
XSP 生成動態(tài)數(shù)據(jù),而不是動態(tài)表示。與之不同,JSP 則是一種通常用于在一系列處理步驟的最后階段產(chǎn)生 HTML 或 XML 的表示層技術(shù)。XSP 頁面為 Cocoon 管道生成 XML 數(shù)據(jù),而由管道創(chuàng)建了所期望的表示。
1.2 XSP 編譯過程
- 解析 XSP 文檔
- 通過使用專用 XSLT 樣式表轉(zhuǎn)換 XSP 頁面,以生成 Java 源代碼
- 通過使用代碼格式化器,在整齊地縮排和格式化源代碼后,存儲結(jié)果 Java 文件
- 將源代碼編譯成生成器
- 在請求管道中裝入并執(zhí)行已編譯的生成器
1.3 一個XSP運行例子
Cocoon 2 提供了一個協(xié)調(diào)個別 XSP 頁面的編譯和執(zhí)行的 ServerPagesGenerator
組件。在網(wǎng)站地圖中,ServerPagesGenerator
聲明如下:
<map:generators default="file">
<map:generator name="xsp" src="org.apache.cocoon.generation.ServerPagesGenerator"/>
<!-- ... other generator declarations ... -->
</map:generators>
要在管道中使用這個生成器,只須簡單聲明應當使用(而不是缺省值)并且指出在何處可以找到特定的 XSP 頁面的源代碼,如下所示:
<map:pipeline>
<map:match pattern="tutorial/*.xml">
<map:generate type="xsp" src="tutorial/{1}.xsp"/>
<map:serialize type="xml"/>
</map:match>
</map:pipeline>
2、語法
2.1 xsp:page 元素
xsp:page
元素是每個 XSP 文檔的根元素。
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">
<!-- page contents -->
</xsp:page>
2.2 xsp:structure 和 xsp:include 元素
當添加利用標準或定制 Java API 的編程邏輯時,必須在 XSP 中指出生成的源代碼中需要另外的 import 語句以確保編譯成功地完成。xsp:structure
和 xsp:include
元素用于向代碼生成過程提供這些附加提示。
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">
<xsp:structure>
<xsp:include>java.util.Calendar</xsp:include>
<xsp:include>java.text.*</xsp:include>
</xsp:structure>
<!-- page contents -->
</xsp:page>
2.3 xsp:logic 元素
xsp:logic
元素用于將 Java 代碼塊添加到 XSP。例如:
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">
<xsp:logic>
public String getTime()
{
return java.util.Calendar.getInstance().getTime().toString();
}
</xsp:logic>
<document/>
</xsp:page>
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">
<document>
<xsp:logic>
SimpleDateFormat format = new SimpleDateFormat("EEE, MMM d, yyyy");
String timestamp = format.format(
java.util.Calendar.getInstance().getTime()
);
</xsp:logic>
<time><xsp:expr>timestamp</xsp:expr></time>
<!-- additional elements -->
</document>
</xsp:page>
這個代碼包含了對 XSP 文檔求值時創(chuàng)建時間戳記的邏輯。然后通過使用 xsp:expr
,這個時間戳記被添加到了 time
元素內(nèi)的文檔中。
2.4 避免錯誤,保持良好的格式
2.4.1
程序代碼與 XML 標記
把 if (a < b && c > d) { ... }改為①if (a < b && c >) { ... }或者②
<xsp:logic>
<![CDATA[
if (a < b && c > d) { ... }
]]>
</xsp:logic>
但是②
將忽略這些節(jié)內(nèi)出現(xiàn)的任何 XSP 或用戶元素,而將它們當作純文本而不是 XML 標記進行處理,這樣更可能導致隱蔽的、耗時的錯誤。
2.4.2
xsp:logic
元素內(nèi) XML格式規(guī)則
以下有錯:
<search-results>
<xsp:logic>
if (firstResult())
{
<result id="first">
} else
{
<result>
}
<!-- ...result generation code here... -->
</result>
</xsp:logic>
</search-results>
應改為
<search-results>
<xsp:logic>
if (firstResult())
{
<result id="first">
<!--... handle first result..-->
</result>
} else
{
<result>
<!--...handle other results...-->
</result>
}
</xsp:logic>
</search-results>
2.5 xsp:expr 元素
xsp:expr
元素等價于在 JSP 中實現(xiàn)類似角色的<%= ... %>
表達式語法。
<elements>
<xsp:logic>
for (int i=1; i<11; i++)
{
<element><xsp:expr>i</xsp:expr></element>
}
</xsp:logic>
</elements>
2.6 通過使用 xsp:element 生成動態(tài)元素
通過使用 xsp:element
,還可以動態(tài)地創(chuàng)建元素,它的工作原理類似于其 XSLT 等價機制的工作原理。
<xsp:element>
<xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param>
Element content
</xsp:element>
還可以與一個特定的名稱空間和前綴關(guān)聯(lián)
<xsp:element prefix="my" uri="http://www.examples.org">
<xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param>
Element content
</xsp:element>
這個示例生成了以下 XML 輸出:
<my:myElementName xmlns:my="http://www.examples.org">Element content</my:myElementName>
還可能動態(tài)地生成名稱空間 URI 和前綴。無須添加 prefix
和 uri
屬性,而是使用帶適當名稱的附加 xsp:param
元素。下列代碼等價于上面的示例:
<xsp:element prefix="my" uri="http://www.examples.org">
<xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param>
<xsp:param name="prefix">"my"</xsp:param>
<xsp:param name="uri">"http://www.examples.org"</xsp:param>
Element content
</xsp:element>
2.7 通過使用 xsp:attribute 生成動態(tài)屬性
xsp:attribute
元素的工作原理類似于 xsp:element
,它允許動態(tài)創(chuàng)建屬性的名稱及其值:
<xsp:element>
<xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param>
<xsp:attribute name="myAttribute">myAttributeValue</xsp:attribute>
Element content
</xsp:element>
這個屬性的名稱定義在 name
屬性內(nèi),盡管是用與 xsp:element
類似的方法定義的,但它還能通過使用 xsp:param
子元素來定義。屬性值被指定成元素內(nèi)容。這可以是一個簡單文本值或更有效地由 xsp:expr
元素生成。
2.8 創(chuàng)建注釋和處理指令
2.8.1 創(chuàng)建注釋:
<xsp:comment>This is a comment</xsp:comment>
然后這個注釋變成:
<!-- This is a comment -->
2.8.2 創(chuàng)建處理指令類似于創(chuàng)建動態(tài)元素或?qū)傩?/SPAN>:
<xsp:pi target="myApplication">
<xsp:expr>"param1=value, param2=value, generatorTimestamp=" +
System.currentTimeMillis()</xsp:expr>
</xsp:pi>
輸出如下:
<?myApplication param1=value, param2=value, generatorTimestamp=1017407796870?>
還可以通過在 xsp:param
元素內(nèi)創(chuàng)建處理指令的目標來自動生成它,如同以下示例演示的那樣:
<xsp:pi>
<xsp:param name="target"><xsp:expr>"myApplication"</xsp:expr></xsp:param>
<xsp:expr>"param1=value, param2=value, generatorTimestamp=" +
System.currentTimeMillis()</xsp:expr>
</xsp:pi>
3 邏輯單
邏輯單是能被鉤接入代碼生成過程以允許創(chuàng)建定制標記庫的 XSLT 轉(zhuǎn)換。這些邏輯單使 XSP 頁面更容易處理,從而減少了直接嵌入代碼的需要。
3.1 使用邏輯單
每個邏輯單都與一個特殊的名稱空間關(guān)聯(lián)。使用邏輯單僅僅涉及在 XSP 文檔中聲明相應的名稱空間,然后在需要的時候添加來自那個名稱空間的元素。
<xsp:page language="java"
xmlns:xsp="http://apache.org/xsp"
xmlns:util="http://apache.org/xsp/util/2.0">
<clock>
<day><util:time format="EE"/></day>
<month><util:time format="MMMM"/></month>
<year><util:time format="yyyy"/></year>
<time><util:time format="HH:mm:ss 'on' dd/MM/yyyy"/></time>
</clock>
</xsp:page>
3.2內(nèi)置邏輯單
3.2.1 環(huán)境邏輯單
在這個環(huán)境類別中有四個邏輯單,每個邏輯單都提供對與 Web 請求關(guān)聯(lián)的處理環(huán)境的特殊方面的訪問。這些邏輯單提供的功能類似于與 JSP 頁面關(guān)聯(lián)的隱式對象(例如,request
和 response
對象)提供的功能,并且是從 HTTP Servlet API 中直接提取的。
1) 請求(request)邏輯單
提供了對請求屬性的訪問,包括對請求參數(shù)、請求方法(例如,GET
、POST
等等)以及請求標題的訪問。當請求參數(shù)的某些方面用于改變輸出文檔的生成時,這個邏輯單就格外有用。
2)響應(response)邏輯單
提供對與當前請求關(guān)聯(lián)的 HTTP 響應的限制訪問;它只提供對請求標題的訪問。XSP 文檔不能用與 Java Servlet 或 JSP 頁面相同的方法執(zhí)行包含或轉(zhuǎn)發(fā),因為分離問題是 Cocoon 2 體系結(jié)構(gòu)的核心部分。這個功能描述在網(wǎng)站地圖中;XSP 頁面生成 XML 內(nèi)容而不指導處理。
3)會話(session)邏輯單
提供了對 HTTP 會話信息的訪問,包括創(chuàng)建和刪除會話以及添加和除去會話屬性的能力。很明顯,這個功能在必須為上下文維護用戶會話的 Web 應用程序中是最有用的。Cocoon 2 中的會話管理正好等價于它的 JSP 對手。
4)cookie 邏輯單
提供了 cookie 維護功能,諸如添加和除去 cookie、允許優(yōu)先存儲到用戶的瀏覽器中。
3.2.2 實用程序邏輯單
1) 日志(log)邏輯單
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp"
xmlns:util="http://apache.org/xsp/log
/2.0">
<log:debug>This is a debug message from an XSP generator</log:debug>
</xsp:page>
2)
發(fā)送郵件(sendmail) 邏輯單
<sendmail:send-mail from="myemail@email.com" to="user@user.com" smtphost="smtphost@email.com">
<xsp:param name="subject"><xsp:expr>"The subject of this email..."</xsp:expr></xsp:param>
<xsp:param name="body"><xsp:expr>"The body of this email..."</xsp:expr></xsp:param>
</sendmail:send-mail>
3) 時間邏輯單
如前面的示例。
3.2.3 數(shù)據(jù)操作
1) 表單驗證器(form validator)邏輯單
表單驗證器(form validator)邏輯單從未真正單獨使用。它向 Cocoon 表單驗證器行為(Cocoon Form Validator Action)提供一個整齊的界面。這個行為能夠?qū)?HTML 表單發(fā)送到 Cocoon 應用程序的數(shù)據(jù)執(zhí)行基本驗證操作,包括檢查整數(shù)的最小和最大值、檢查字符串的大小以及檢查提供的某些參數(shù)。一個著名功能是能夠測試傳遞的變量是否匹配給定的正則表達式。
2) esql 邏輯單
esql 邏輯單提供了執(zhí)行這一步的方法,并提供了更多的功能,包括選擇、刪除和更新數(shù)據(jù)庫。本質(zhì)上,esql 邏輯單提供了將 SQL 語句直接嵌入到 XSP 文檔的方法。然后這個邏輯單生成相應的 JDBC 代碼來實現(xiàn) SQL 操作,這樣通過使用 Cocoon 2 簡化了對數(shù)據(jù)庫數(shù)據(jù)的操作和檢索。
3.3 編寫邏輯單
因為邏輯單轉(zhuǎn)換可能以任何順序發(fā)生,所以每個邏輯單都需要保留輸入文檔中它不理解的任何內(nèi)容。換句話說,邏輯單的基本模板是恒等轉(zhuǎn)換。這是一個將它的輸入未做更改而直接簡單復制到它的輸出的轉(zhuǎn)換。
<xsl:template match="time:time">
<xsp:logic>
SimpleDateFormat timeFormat = new SimpleDateFormat("<xsl:value-of select="@format"/>");
</xsp:logic>
<xsp:expr>
timeFormat.format(java.util.Calendar.getInstance().getTime())
</xsp:expr>
</xsl:template>
該單一模板與 time
元素匹配,并用封裝在 xsp:logic
和 xsp:expr
元素中的代碼來替代它們以創(chuàng)建日期。所需的日期格式由用戶通過這個元素上的 format
屬性來說明。
3.4 配置邏輯單
在該配置文件中搜索 xsp-language
元素,并注意它包含一個名為 target-language
的子元素。應聲明這個元素內(nèi)的所有邏輯單。還可能看到已預先定義了內(nèi)置邏輯單。這里是 util 邏輯單的項:
<builtin-logicsheet>
<parameter name="prefix" value="util"/>
<parameter name="uri" value="http://apache.org/xsp/util/2.0"/>
<parameter name="href" value="resource://org/apache/cocoon/components/language/markup/xsp/java/util.xsl"/>
</builtin-logicsheet>
另例如:
<!--*************** Test By David *************** -->
<builtin-logicsheet>
<parameter name="prefix" value="xsp-time"/>
<parameter name="uri" value="$CATALINA_HOME/webapps/cocoon/WEB-INF/classes/logicsheets/time.xsl"/>
<parameter name="href" value="resource://logicsheets/time.xsl"/>
</builtin-logicsheet>
3.5 邏輯單的開發(fā)技巧
3.5.1 使用助手類:
雖然創(chuàng)建邏輯單將從 XSP 頁面中提取出程序代碼,但這個代碼仍被鎖藏在 XSLT 樣式表中。這使不依賴 Cocoon 而要維護和測試代碼很困難。一個好的設(shè)計技巧是將盡可能多的代碼放入助手類中。這樣使得邏輯單的實現(xiàn)簡化為只是收集參數(shù),然后調(diào)用所需的助手方法。內(nèi)置邏輯單遵循這個指南,并且每個邏輯單都有單個助手類。
3.5.2 創(chuàng)建邏輯單“宏”:
宏是記錄和重新執(zhí)行一系列操作的一個簡單快速的方法。在特殊應用程序中的 XSP 頁面可能要重復創(chuàng)建相同的 XML 結(jié)構(gòu)或用同樣的方法調(diào)用其它邏輯單。提取出 XSP 頁面中的公共塊,以創(chuàng)建描述這個重復結(jié)構(gòu)的較高級別元素(例如,宏)是很有用的。因為 Cocoon 2 遞歸地應用邏輯單,直到處理完所有名稱空間為止,一個邏輯單的實現(xiàn)可以添加另一個邏輯單上的元素。這種組合可以大大降低 XSP 頁面的復雜程度。
3.5.3 考慮用戶:
當考慮在邏輯單中提供什么樣的標記時,請考慮最終用戶。他們需要怎樣的靈活性?例如,可以將什么樣的參數(shù)發(fā)送給標記?只能通過屬性或嵌套的 xsp:param
元素發(fā)送參數(shù)嗎?后者更加靈活,因為它允許用戶通過使用 xsp:expr
動態(tài)地創(chuàng)建參數(shù)值,而 xsp:expr
不能在屬性內(nèi)使用。還要考慮如何命名標記。賦予它一個清晰和好記的名稱,這樣它所做的就顯而易見了。并不是每個人都樂意深入研究邏輯單的實現(xiàn)來感受這一點的。這個建議的一個很明顯擴展是向邏輯單提供支持文檔;這使用戶能快速找到標記的含義以及如何使用它。