你盡可以做個良民,為群體效率而本份的遵循個人秩序,然而事與願違,非但 不能因此提升群體的效率,而你勢必失去諸多的機會,不會有人褒獎你,更得不 到同情,只得自覺的天真。
1. 模板目錄->主題目錄->主題(模板文件) 這是模板/主題的目錄組織方 式。以實際為例,打開 struts2-core-2.x.x.jar 可以看到裡面有一個 template ,在 template 下有5個目錄 ajax、css_xhtml、simple、xhtml 和 archive,其 中前四個分別是 ajax、css_xhtml、simple、xhtml 主題的目錄,每個主題目錄 中有各自的模板文件,主要是 ftl 文件,還有 css和 js 文件。最後一個 archive 是歸檔的主題目錄,其下又有 ajax、simple、xhtml、模板文件是 .vm 文件。由此可知 Struts2 大力推薦的模板語言是 FreeMarker,而不是 Velocity ,以後要好好看看 FreeMarker,只知道 FreeMarkder 更 XML 化。
2. 上面看到模板目錄名是 template,是 struts2-core-2.x.x.jar 中,其實 目錄名是由 struts.ui.templateDir 常量來指定的,只是默認值是 template。 意味著 Struts 2 從 Web 應用的 template 目錄或CLASSPATH 的 template 目錄 (包) 中依次加載特定的模板文件。
3. 比如我們使用一個 select 標簽,且指定主題為 xhtml,則加載模板文件 的順序為 (1) Web 應用/template/xhmlt/select.flt (2) CLASSPATH/template/xhtml/select.ftl。Struts2 默認是用的 FreeMarkder 模 板技術,可設置常量 struts.ui.templateSuffix 來改變默認的模板技術,可選 值有 ftl、vm、jsp。但是對於 vm 和 jsp 要自己提供完整的實現,Struts2 可 沒幫你做這些。
4. 有時候我們想要自定義主題,如你希望輸入框前的標簽顯示紅顏色,你不 想要校驗錯誤提示在輸入框正上方而是右邊。當然你可以修改 struts2-core- 2.x.x.jar 中 template 下某個主題的模板文件,或拷一份到 Web 應用目錄的 template 目錄修改要定制的模板,這樣做總有些不爽。Struts2 還支持兩種更靈 活的主題定制方式。包裝和繼承現有主題,可以同時使用。
最簡單的主題定制方式是利用主題模板的加載優先級,把自定義的模板文件放 在優先級高的目錄,比如放一個 text.ftl 在 WEB- INF/classes/template/xhtml/ 目錄下,它將覆蓋掉 struts2-core-2.x.x.jar 裡的 template/xhtml/text.ftl 的定義。
5. 先看一個包裝的例子,在 xhtml 下的 combobox.ftl 的內容如下:
<#include "/${parameters.templateDir}/ ${parameters.theme}/controlheader.ftl" />
<#include "/ ${parameters.templateDir}/simple/combobox.ftl" />
<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" /><#nt/>
它就是對 simple/combobox.ftl 的基礎上包裝上一個 controlheader.ftl 和一 個 controlfooter.ftl,包裝的局限性是你仍然是要為每一個 UI 組件提供單獨 模板文件,即全套的。
和設計模式中的包裝(裝飾)模式如出一轍,如 BufferedInputStream 包裝了 InputStream,但在 BufferedInputStream 提供了全套的和 InputStream 一樣 的操作方法。
6. 再說繼承來自定義主題,如果簡單改變個別 UI 的風格,繼承就是最為高 效的了。此繼承與 Java 的繼承(即extends) 也是一馬事。要改變或要新加的用 自己定義的,其他的延用父主題的。舉個例子,自定義一個名為 custom 的主題 繼承自 xhtml,只改變 select 標簽的風格,你要做的就是編輯自己的一個 select.ftl 放在 WEB-INF/classes/template/custom 下,並在此目錄下放一文 件 theme.properties,內容是:
#指定該主題以 xhtml為基礎進行擴展
parent=xhml
使用可指定給 UI 標簽,例如 <s:form name="aa" theme="custom" ..., 效果就會是 form 下的 select 使用了在 custom 目錄下自定義的 select.ftl, 其他的直接使用父主題 xhtml 中的模板文件。Struts2 提供的 ajax 主題就是繼 承自 xhtml 主題的。
7. 簡單說一下 Struts2 的內建主題,包括 simple、xhtml、css_xhtml 和 ajax。simple 主題不用多說,比Struts1 的 html 標簽還弱些,只對應簡單的 html 元素,不生成額外內容。xhtml 是默認主題,是對 simple 主題的包裝和擴 展(也就是繼承),該主題下有一個 head.ftl 用來導入 javascript 類庫(如 dojo)。xhtml 在 simple 的基礎上增加了以下特性:
1) 針對 HTML 標簽(如 textfield和select標簽) 使用標准的兩列表格布局
2) 每個 HTML 標簽有 label 屬性,默認左邊顯示,可通過 labelposition 屬性設定位置
3) 自動輸出後台校驗錯誤或 javascript 前端校驗錯誤
8. 繼續 Struts2 的內建主題的話題。css_xhtml 主題是對 xhtml 的擴展, 顯示是加入了 css 樣式控制特性。ajax 主題是對 xhtml 主題的擴展,在 xhtml 主題的每個標簽增加了 ajax 的支持(以 Djoj 和 DWR 為基礎)。所增 Ajax 特性 有:
1) Ajax 方式的客戶端校驗
2) 遠程表單的異步提交
3) 高級 div 標簽,允許局部更新
4) 高級 a 標簽,允許動態加載並執行遠端的 javascript 代碼。
5) 提供支持 ajax 的 tabbedPanel
6) 提供“富客戶端” 模型的 pub-sub 事件模型
9. 先前有網友問過我,他用了 Struts2 的校驗,但是錯誤輸出是在輸入框的 上方,但希望錯誤信息是顯示在輸入框的右方,該如何做。當時我只告訴了他要 修改模板文件,也只是大概告訴了他是在某個 template 目錄下的一個 ftl 文件 ,因那時具體操作自己也不太清楚。現在知道了線索,但實際修改還是很麻煩的 。
輸入框 <s:textfield .../> 默認是用的 xhtml/text.flt 模板, text.ftl 包裝了 smple/text.ftl,錯誤信息可以追溯發現是在 controlheader -core.ftl 中定義顯示的,所以你可以把 xthml/text.ftl 和 controlheader- core.ftl 拷到 WEB-INF/classes/template/xhtml 目錄中進行修改,WEB- INF/classes/template/xhtml 中的模板文件是優先於 struts2-core-2.x.x.jar 裡的 template/xhtml 目錄中的模板文件加載。
10. 看有些地方只籠統介紹說:所有表單元素都存在一個特殊的屬性:form, 這個屬性引用元素所在表單,通過該屬性實現表單元素與表單間的交互,例如可 通過 ${parameters.form.id} 訪問表單的 ID。對這句話我只是感到一頭霧水, 查看像 <s:textfield .../> 等標簽並無 form 屬性,用 <s:textfield value="${parameters.form.id}" name="aa"/>也看不到輸 出所在表單的 ID。去網上找找,才知道前面那句話有出入,其實說的是在主題模 板文件裡的用法,打開一些主題模板文件,如 combobox.ftl 或 controlheader -core.ftl 文件,你就能看到許多的 parameters 的表示法-- parameters.required、parameters.id。想見一下 parameters 屬性才是根本, 它代表了表單元素的屬性集,parameters 說來還有點像 this,this.id、 this.form.id、this.required 等等...