tpl是witrix開發平臺中的動態xml標簽技術,其基本特點表現為如下三個方面:
1. 執行能力
xml本身只是對數據的描述,而沒有循環和判斷的能力。
在tpl中<c:forEach>和<c:if>標簽可以完成程序語言的執行功能,并定義了<c:tile>, <c:iif>等更方便的標簽。
2. 抽象能力
獲得抽象能力,首要的一點是使得創建新概念的成本極低。很少有人大量開發jsp tag,原因就是開發tag過于麻煩,而且調整不方便。另外開發出的tag如果粒度太小,大量使用的時候是對性能的致命傷害。
tpl首先需要經過編譯,而不是象jsp tag那樣完全動態運行,而且tpl編譯出的結果是無狀態的,因此解決了性能上的問題。
在tpl中導入外部模板的語法非常簡單,可以實現基本的分解
<c:include src="xxx.tpl" />
更重要的是,tpl中定義了完善的庫機制。
使用庫
<!-- 導入外部包, 導入時指定名字空間為demo。
注意tpl中并沒有完整的名字空間支持,只能作為qName使用
-->
<c:lib src="demo_lib.xml" namespace="demo" />
<!-- 對具有cache:timeout屬性的節點應用cache修飾,即該節點的運行內容被緩存 -->
<c:decorator type="cache" match="//@[cache:timeout]" />
<div id="blockA">
<p>通過tpl:tag屬性可以設定宿主標簽的真實標簽名。這種做法可以方便可視化設計:</p>
<input tpl:tag="demo:文本框" value="in block A"
otherValue="${varInJsp}" onclick="clickOnBtn()"/>
</div>
<div id="blockB">
<p>分頁表格:</p>
<img tpl:tag="demo:分頁表格" headers="fieldA,fieldB" pager="${pager}" />
</div>
<div id="blockC">
<p>bodyTag標簽的調用:</p>
<demo:循環data>
<input type="text" value="${row}" /> <br/>
</demo:循環data>
</div>
<div id="blockD" cache:timeout="1000s" >
<p>條件標簽的調用:</p>
<demo:當Num足夠大>
<p>當 thisObj中的變量 'num' 的值大于3的時候顯示這句話 </p>
</demo:當Num足夠大>
</div>
定義庫文件demo_lib.xml
<!--
自定義標簽的屬性:
type: simpleTag, bodyTag 或者 conditionTag, 缺省為simpleTag
importVars : 每個自定義標簽具有自己的變量空間,需要通過importVars來明確指定從外部變量空間中導入的變量。
demandArgs: 調用時必須明確給出這些參數的值
otherArgs: 如果指定了該參數,則調用自定義標簽時能夠使用的參數就必須在demandArgs和otherArgs指定的范圍之內。
-->
<demo>
<!-- 一個簡單的tag示例, 直接輸出變量。這里demandArgs指定調用時必須提供的變量。 -->
<文本框 demandArgs="value" otherArgs="otherValue,onclick" type="simpleTag" >
<p> ----------------------------------- </p>
<!-- 可以使用調用時提供的其他變量,如otherValue-->
<input size="40" type="text" value="${value} * ${otherValue}" onclick="${onclick}"/>
<p> -----------------------------------</p>
</文本框>
<!-- 一個自動分頁表格,要求傳入headers(List類型)指定表頭,pager(Pager類型)提供數據 -->
<分頁表格 demandArgs="headers,pager">
<!-- 從外部導入tpl文件 -->
<c:include src="flex_table.tpl" />
</分頁表格>
<!-- 一個bodyTag示例: 循環處理thisObj中的變量data中的每一行。
importVars從調用環境中自動導入變量而不需要通過調用參數直接指定。
當然如果調用參數中指定的變量與importVars中指定的變量重復,則調用參數會覆蓋importVars.
-->
<循環data importVars="thisObj" type="bodyTag">
<c:forEach var="row" items="${data}">
<!-- tagBody為調用時標簽的內容 -->
<cp:compile src="${tagBody}" />
</c:forEach>
</循環data>
<!-- 一個條件標簽的示例.
條件標簽一般不應該輸出文本,而是返回一個bool值。僅當返回true的時候,調用時標簽的內容才會被運行。
-->
<當Num足夠大 importVars="thisObj" type="conditionTag">
<l:gt name="num" value="3" />
</當Num足夠大>
</demo>
注
意到bodyTag和conditionTag使得我們可以將循環(容器)邏輯和判斷邏輯抽象成有意義的概念,而不再是一些執行的指令。這種抽象能力的應
用非常依賴于xml的自描述特性,我們不需要付出太大的努力,就可以在lib中封裝出一個有意義的概念來!
而且tag的參數可以指定,可以缺省,存在多種選擇,也對應著多種邏輯模型。
通過<c:decorator>的用法可以看到,因為xml明確定義了結構,使得我們可以輕易的實施類似AOP的功能。
3. 集成能力
首先,tpl完全符合xml規范,與xml世界接軌,可以自由的使用xslt。例如,在
任何標簽中都可以指定tpl:xdecorator屬性, tpl在編譯之前首先會應用指定的xslt文件進行變換,對變換后的結果再進行編譯。
<anyTagName tpl:xdecorator="some_xslt.xslt">
...
</anyTagName>
其次,tpl可以使用屬性標記,即tpl標簽不僅僅可以通過標簽名來標識,而且可以通過tpl:tag屬性來標識。例如:
<input tpl:decorator="demo:文本框" />
與 <demo:文本框 />等效。
這種做法避免了tpl侵入html模型,使得我們可以利用現有工具對tpl進行所見即所得(WISIWIG)的設計。
再次, 在tpl中使用EL(Expression Language)語言,集成java數據模型。
第四, 在tpl中可以采用如下方式實現強類型化,完成與java的接口。
interface ITest{
void test(String name, int value);
}
<o:class name="MyClass" implements="ITest">
<test args="name,value" >
...
</test>
</o:class>
這種能力可以在數據源的filter中使用。
第五, tpl可以輕易的集成其它xml技術。例如,tpl集成了ant
<ant:run>
<echo message="xxx" />
</ant:run>
因此,我們立刻擁有了ant的數千個功能標簽。