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