基于模板的Web表示層技術(shù) (摘自《Spring開(kāi)發(fā)指南》)
傳統(tǒng)的JSP技術(shù)為Web表現(xiàn)層技術(shù)提供了靈活、豐富的功能支持。然而,站在工程的角度
而言,過(guò)于凌亂的JSP Script也成為系統(tǒng)維護(hù)的頭號(hào)大敵。
JSP 代碼幾乎等同于Java 代碼,在提供了最豐富的特性支持的同時(shí),也為系統(tǒng)的開(kāi)發(fā)帶
來(lái)一些隱患,程序員往往天馬行空,不為羈束,在JSP 中將業(yè)務(wù)邏輯、數(shù)據(jù)邏輯、表現(xiàn)邏輯代
碼相混雜,代碼重用性、系統(tǒng)可維護(hù)性極低。特別是在參與開(kāi)發(fā)人員眾多,技術(shù)水平良莠不齊
的情況下,縱使技術(shù)經(jīng)理一再?gòu)?qiáng)調(diào)設(shè)計(jì)規(guī)范的約束,但人本的約束總是難以控制,隨著開(kāi)發(fā)過(guò)
程進(jìn)展和產(chǎn)品上線壓力的增大,規(guī)范約束逐漸薄弱,于是難以避免的造成代碼的混亂,可維護(hù)
性的下降。
面對(duì)這個(gè)問(wèn)題,眾多組織和廠商開(kāi)始研發(fā)自己的表現(xiàn)層框架,試圖通過(guò)一個(gè)隔離的表現(xiàn)層
框架,強(qiáng)行將表現(xiàn)層和邏輯層相剝離。時(shí)間似乎退回到了最初Web 端只支持Servlet 技術(shù)的
時(shí)代(那時(shí)候或多或少各個(gè)公司都有自己的模板實(shí)現(xiàn))。不過(guò),現(xiàn)在的模板技術(shù)經(jīng)過(guò)長(zhǎng)時(shí)間的
發(fā)展,已經(jīng)將表現(xiàn)層的能力發(fā)揮得淋漓盡致,不失為JSP技術(shù)之外的一個(gè)明智選擇。
模板技術(shù)相對(duì)傳統(tǒng)JSP技術(shù)有以下三個(gè)主要優(yōu)勢(shì):
1. 在技術(shù)層面,將表現(xiàn)邏輯與業(yè)務(wù)邏輯相分離。
2. 為人員之間的分工提供了一個(gè)良好的分界點(diǎn)。頁(yè)面美工只需專(zhuān)著關(guān)心模板的設(shè)計(jì),而程序員則專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn)。二者重合點(diǎn)明顯減少。
3. 如果需要,模板引擎可脫離Web 容器單獨(dú)運(yùn)行,這為系統(tǒng)可能的移植需求提供了更多的彈性空間(這一特性在應(yīng)用中也許并不會(huì)有太大的實(shí)際意義,只是提供了一種附加選擇)。
目前Spring支持一下幾種模板技術(shù):
1. XSLT
XSLT是基于XML的表現(xiàn)層模板技術(shù),伴隨著XML的大量使用。XSLT也日漸成熟,并
迅速成為主流表現(xiàn)層技術(shù)之一。XSLT作為一個(gè)通用表現(xiàn)層框架,擁有最好的平臺(tái)適應(yīng)性,
幾乎所有的主流程序設(shè)計(jì)語(yǔ)言都提供了XLST支持,現(xiàn)有的XLST模板可以簡(jiǎn)單的移植到不
同的語(yǔ)言平臺(tái),如將J2EE應(yīng)用中的XSLT移植到.net平臺(tái),這樣的可移植性是其他專(zhuān)用
模板技術(shù),如Velocity和Freemarker難以達(dá)到的。
筆者在2001年在一個(gè)原型項(xiàng)目中采用了XSLT作為表現(xiàn)層實(shí)現(xiàn),由于當(dāng)時(shí)XSLT尚不
成熟,XSLT解析器效率低下,因此在正式產(chǎn)品開(kāi)發(fā)中使用其他技術(shù)作為替代。在2003年
中,經(jīng)過(guò)技術(shù)探討,決定再次在項(xiàng)目實(shí)施中引入XSLT 技術(shù),相對(duì)兩年前,此時(shí)的XSLT
技術(shù)已經(jīng)相當(dāng)成熟,解析器的效率也大大改善。經(jīng)過(guò)半年時(shí)間的項(xiàng)目研發(fā),產(chǎn)品上線,并
取得了令人滿意的表現(xiàn)。不過(guò),在之后的項(xiàng)目回顧過(guò)程中,筆者認(rèn)為,目前在項(xiàng)目中大量
采用XSLT技術(shù)尚不可取,上述項(xiàng)目開(kāi)發(fā)過(guò)程中,XSLT技術(shù)提供了極佳的擴(kuò)展性和重用性,
也保證了業(yè)務(wù)邏輯和表示邏輯的清晰劃分,然而,最大的問(wèn)題是,XSLT缺乏強(qiáng)有力的編輯
器支持。雖然通過(guò)XML/XSLT 技術(shù)成全了設(shè)計(jì)上近乎完美的表現(xiàn),但卻為界面開(kāi)發(fā)帶來(lái)了
極大難度,以至后期復(fù)雜界面的修改都需要消耗極大的人力,得不償失。
筆者在項(xiàng)目開(kāi)發(fā)中所用的XSLT 編輯器為StylusStudio 和XmlSpy,目前這兩款編
輯器可以算是XSLT開(kāi)發(fā)的首選,提供了豐富的特性和可視化編輯功能。但即便如此,XLST
繁雜苛刻的語(yǔ)法和調(diào)試上的難度也為開(kāi)發(fā)工作帶來(lái)了極大的障礙。
此外,也許是最重要的一點(diǎn),xslt在性能上的表現(xiàn)尚不盡如人意。經(jīng)過(guò)多年的發(fā)展,
XSLT解析/合成器的性能相對(duì)最初已經(jīng)大為改觀,但依然與其他模板技術(shù)存在著較大差距。
據(jù)實(shí)地測(cè)試,F(xiàn)reeMarker和Velocity對(duì)于同等復(fù)雜度的表現(xiàn)層邏輯,平均處理速度是
XSLT 的10 倍以上,這是一個(gè)不得不正視的性能溝壑。同時(shí),XSLT 的內(nèi)存占用也是
FreeMarker 和Velocity 的數(shù)倍有余(XSLT 中,每個(gè)節(jié)點(diǎn)都是一個(gè)Java 對(duì)象,大量
對(duì)象的存儲(chǔ)對(duì)內(nèi)存占用極大,同時(shí)大量對(duì)象的頻繁創(chuàng)建和銷(xiāo)毀也對(duì)JVM 垃圾收集產(chǎn)生了較
大負(fù)面影響)。在上述項(xiàng)目中,由于硬件上的充分冗余(8G RAM, 4CPU),才使得這些
性能上的影響相對(duì)微弱。
因此,目前在項(xiàng)目中大量引入XSLT技術(shù)尚需仔細(xì)考量。
2. Velocity
Velocity是Apache Jakarta項(xiàng)目中的一個(gè)子項(xiàng)目,它提供了豐富強(qiáng)大的模板功能。
作為目前最為成熟的模板支持實(shí)現(xiàn),Velocity 在諸多項(xiàng)目中得到了廣泛應(yīng)用,不僅
限于Web 開(kāi)發(fā),在眾多代碼生成系統(tǒng)中,我們也可以看到Velocity 的身影(如
Hibernate中的代碼生成工具)。
3. FreeMarker
FreeMarker是Velocity之外的另一個(gè)模板組件。
與Velocity 相比,F(xiàn)reeMarker 對(duì)表現(xiàn)邏輯和業(yè)務(wù)邏輯的劃分更為嚴(yán)格,
Freemarker在模板中不允許對(duì)Servlet API進(jìn)行直接操作(而Velocity可以),
如FreeMarker 中禁止對(duì)HttpServletRequest 對(duì)象直接訪問(wèn)(但可以訪問(wèn)
HttpServletRequest對(duì)象中的Attribute)。通過(guò)更加嚴(yán)格的隔離機(jī)制,牽涉邏
輯處理的操作被強(qiáng)制轉(zhuǎn)移到邏輯層。從而完全保證了層次之間的清晰性。
另外一個(gè)Velocity無(wú)法實(shí)現(xiàn)的特性,也是最具備實(shí)際意義的特性:FreeMarker對(duì)
JSP Tag提供了良好支持。這一點(diǎn)可能存在一點(diǎn)爭(zhēng)議,JSP技術(shù)的最大問(wèn)題就是容易
在頁(yè)面中混入邏輯代碼。而FreeMarker 對(duì)JSP Tag 的支持似乎為這個(gè)問(wèn)題又打開(kāi)
了大門(mén)。這一點(diǎn)上,我們可以將FreeMarker看作是僅允許使用TAG的JSP頁(yè)面(實(shí)
際上,F(xiàn)reeMarker的表達(dá)式語(yǔ)法與EL語(yǔ)法也非常類(lèi)似)。
從開(kāi)發(fā)角度而言,只允許使用TAG的JSP頁(yè)面,已經(jīng)在很大程度上保證了頁(yè)面表現(xiàn)邏
輯與業(yè)務(wù)邏輯的分離。程序員在JSP Script中混雜邏輯代碼的原因,大部分是出于
慵懶,只要無(wú)法在頁(yè)面模板中直接編寫(xiě)Java代碼,相信程序員也不會(huì)去專(zhuān)門(mén)編寫(xiě)一個(gè)
JSP TAG來(lái)刻意違反層次劃分原則。
對(duì)JSP TAG 的支持為FreeMarker 帶來(lái)了極大的活力,目前開(kāi)源社區(qū)中已經(jīng)有了為
數(shù)眾多的成熟Taglib,如DisplayTag、Struts Menu等,這些功能豐富,成熟可
靠的Taglib,將為產(chǎn)品開(kāi)發(fā)提供極大的便利。另一方面,這也為代碼重用提供了另一
個(gè)可選途徑,避免了大部分模板實(shí)現(xiàn)在這一點(diǎn)上的不足。
就筆者的經(jīng)驗(yàn),對(duì)于Web開(kāi)發(fā)而言,F(xiàn)reeMarker在生產(chǎn)效率和學(xué)習(xí)成本上更具優(yōu)勢(shì),
而Velocity 的相對(duì)優(yōu)勢(shì)在于更多第三方工具的支持和更廣泛的開(kāi)發(fā)和用戶(hù)團(tuán)體(然
而對(duì)于一個(gè)輕量級(jí)模板類(lèi)庫(kù)而言,這樣的優(yōu)勢(shì)并不是十分明顯)。
如果沒(méi)有Velocity的技術(shù)儲(chǔ)備,而又需要通過(guò)技術(shù)上的限定解決視圖/模型的劃分問(wèn)
題,這里推薦采用FreeMarker作為Spring MVC中的表現(xiàn)層實(shí)現(xiàn)。以獲得最好的(學(xué)
習(xí)、開(kāi)發(fā))成本受益。