<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    buaawhl

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      3 隨筆 :: 5 文章 :: 2 評論 :: 0 Trackbacks

    Web 顯示層技術評估

    名詞界定

    顯示層的意思就是 Presentation Layer ,也翻譯成表現層、展現層、展示層。

    本文討論的范圍只包括采用 HTML Template 的顯示層技術,不包括 Echo GWT(google web toolkit) 等根據代碼產生 HTML 的工具。

    本文主要討論 Server Side ( 針對 Java Language) 的顯示層技術,然后進一步討論 Browser Side Ajax )的顯示層技術(一個典型的 Ajax 應用也分為 Model, View, Controller – Data, HTML/CSS, JavaScript )。注意,本文關于 Ajax 的討論只有很少一部分,因為我不擅長這個領域。只是一個順便的擴展比較。

    一個很有趣的現象。 Server Side Browser Side 的顯示層技術格局恰好相反。 Server Side Scripted Template 技術比較多,比較流行;而 Browser Side HTML DOM Manipulation 技術、 HTML View Model 技術比較多,比較流行。

    本文會提到一些技術、或者框架的名稱,但只局限于討論該技術、該框架的顯示相關部分的內容,而不涉及評估其他方面的特性。比如,本文不討論 Link URL Generation, Action URL Generation Button Script Generation 這些頁面組件事件機制的方面。

    本文是一個深度討論。不討論簡單的替換個字符串的 Hello World 案例,而是窮盡各種顯示層技術的能力極限,探索它們在復雜布局(動態 include 等)、復雜顯示邏輯(條件、循環、嵌套、遞歸)等方面的功能。

    ?

    對了,(考慮到 Site Mesh Struts Tiles Taglib 等技術廣泛的群眾基礎),可能需要專門提一下,本文將不討論 Site Mesh Tiles 等布局技術( named include )。

    Site Mesh 相當于 XSL 的一個簡化版本,只保留了根據 (name->file) 配置替換某個 HTML Node 的能力,其余的如 Tiles ,也大致如此,由于多了一個 (name->file) 配置文件,比直接 include file 高級了不少。

    由于使用簡單(功能自然也簡單),這類技術獲得了廣大群眾的支持,呼聲很高。本文為忽略了這一類技術感到很遺憾。

    ?

    另外需要指出的是,并不存在一個十全十美的方案。

    工作總是要做的,不是在 Template 里面做,就是在 Java Code 里面做,總之,總要找個地方做這個工作,天下沒有免費的午餐。一方面特性增強了,自然影響到另一方面。

    正如,代碼的耦合實際上并不能完全消除,我們只能把這些耦合點移動來移動去,今天我看這里不舒服了,把耦合點移動到另一個地方;明天另一個人看到那里不舒服了,又移動回來。而且各自都能說出一大堆道理。

    所以,需要注意的是,并不存在一個絕對的優勝方案。本文只是列出各種技術指標的參考評估數據,以便幫助讀者根據自己的需要,做出比較準確的評估。(是的,準確的量化評估,而不是廣告語或者口號)

    理論模型

    一個顯示的整個過程,如果用一個函數來描述,那么看起來大概是這樣。

    F(Data, Template, Display Logic) => Result HTML

    其中的 Display Logic ,就是顯示邏輯。 Display Logic 操作 Data Template ,產生最終結果。

    這個 Display Logic 可能以各種形式出現在任何地點。

    比如,可能作為 Server Side Script 存在于 Template 里面,把 Data 取出來輸出;也可能存在于后臺 Java 里面,根據 Data 操作 Template Node

    針對前一種情況,函數公式表達是: Template Script (Data) => Result

    針對后一種情況,函數公式表達是: Logic (Data, Template) => Result

    ?

    這個模型可以作為顯示層技術的劃分標準。

    (1) Scripted Template

    HTML Server Side Script 混雜在一起的顯示層技術。

    包括 JSP, Velocity, Freemarker, Taglib, Tapestry, XSL 等。

    肯定有人對這個劃分有異議。 XSL 里面有 choose, if, for 。這還好說。尤其是對 Taglib, Tapestry ,反映可能更加強烈。我似乎已經看到, Taglib or Tapestry Fans 已經跳起來了,高叫著, Taglib or Tapestry 明明是組件技術,組件技術,組件技術 ….

    這里我還是表示很遺憾。在目前定義的這個狹義模型下,任何 Template 中包含 Logic 的顯示技術都劃為 Script 這一類。而且在表示邏輯的時候,這類組件技術表現的更加突出一些。

    比如 Tapestry <foreach> <if><if-not> <let><set> 等邏輯標簽。尤其是這個 if not ,是專門多出來的一個條件語句,一般的編程語言里面都不具備這樣的對應語法。當然, Tapestry 并不專美, Taglib Logic Tag 也是如此。

    ?

    (2)Template Manipulation

    Java 代碼直接操作 Template (比如, HTML DOM )產生結果的顯示層技術。

    包括 XMLC, JDynamiTe, Rife 等。

    大家對這一類技術可能不是很熟悉。后面進行特性分析的時候,會舉出一些典型的例子,來說明各自的用法。

    一個很有意思的現象是,在 Browser Side Ajax ),由于 Java Script 操作 HTML DOM 非常方便,這類顯示技術非常普遍。相反的, Scripted Template 的技術,在 Browser Side 卻不多見。后面討論 Browser side 的時候,會列舉一些典型的例子。

    ?

    (3) Model Match

    Java 代碼負責提供符合顯示層要求的 Data Model ,顯示層框架本身把 Data Model Template 進行匹配,產生結果。

    包括 Wicket, Fastm, DOMPlus, 等。

    Wicket 如同 Swing 的用法,需要為不同的 UI Component 提供不同的 View Model ,比如 Table, List, Label 等。 Fastm, DOMPlus 支持 POJO ,但同樣需要滿足一些框架特有的約定。

    也許有人會說,某些 Display Tag Lib, Tapestry Components 可能也需要 Java Code 提供特殊的 View Data Model

    不過,需要特殊的 View Data Model ,并不是一個好的特性,意味著不支持 POJO

    數據尋址

    在正式開始之前,先說明一下數據尋址的概念。

    數據尋址,意思是數據訪問、屬性獲取等。主要包括兩類風格。

    (1) OGNL Style

    http://www.ognl.org/

    OGNL (Object Graph Navigation Language) 如此著名和深入人心,以至于我在這里用 OGNL Style 代表 Java Bean 屬性尋址的方式。

    比如, a.b[1].c.d[2].name

    另一類當然是

    (2)XPath Style

    比如, a/b[1]/c/[d]/@name

    XPath Style 主要應用在 XSL 中。

    一個 JXPath 項目能夠按照 XPath 的方式訪問 Java Bean 屬性。

    http://jakarta.apache.org/commons/jxpath/

    ?

    簡單的尋址, OGNL XPath 能夠對應起來。但是, OGNL XPath 都各自是功能很強大的語言,復雜的用法并不能對應。

    評估指標

    下面列出一系列比較詳細的、能夠落到實處的、能夠客觀量化的、可操作的評估硬指標。

    排名不分先后。大家可以參考各自關心的選項。

    雖然下面主要針對的都是 Java Web 顯示技術,但這些指標同樣適用于其他語言的 Web 顯示技術。

    評分采取 10 分作為滿分。

    (1) Host Language Consistency 宿主語言一致性

    Server Side Template Script Server Host Language 是同一種語言。這應該是專門針對 JSP 的優勢來說了。 JSP 能夠獲得 10 分。

    另外, XSL 也是。 XSL 本是也是 XML 格式。也能夠獲得 10 分。

    其他的 Template Script ,如 taglib,tapestry 只能獲得 0 分。

    freemarker, velocity 由于具有一定的動態解釋的方便特性,可以獲得 2 分。

    至于在 Java Code 里面操作 Template 或者提供匹配數據的那些技術,由于 Template 中不存在 Script Logic ,能夠獲得 5 分。

    大家可能不太注意這個特性。但是這個特性還是有一些意義的。其他的如 ASP.net ,還有動態語言, Ruby, Python, PHP, Perl 等,都是 Template Script 和宿主語言一致。

    這能夠一定程度上降低學習成本。尤其是宿主語言比較適合作為 Script 的情況下。

    ?

    (2)Template Purity 模板純凈度

    這主要是指 Template 里面沒有 Script Logic 代碼污染。

    這方面,所有的 Scripted Template 技術都只能獲得 0 分。

    XMLC 能夠獲得 10 分,只利用 HTML 本身的 Attribute ,沒有增加任何自定義 DOM Attribute

    Wicket, DOMPlus 能夠獲得 9 分,它們增加了一部分自定義 DOM Attribute

    JDynamiTe, Fastm 能夠獲得 7 分,它們采用了 XML Comment 作為自定義結構標簽。

    Rife 也能夠獲得 3 -- 7 分,具體看它采用什么標簽格式。

    (3)Template Tidiness 模板整潔度

    主要是指 Template 的格式是否整齊規范。 Taglib,?XSL 無疑是勝利者,本身就是 XML 格式,通用的 XML Parser 就可以解析它們,比較容易在 IDE Plugin 中處理。

    XMLC, Taglib, XSL 能夠獲得 10 分。

    Tapestry, Wicket, DOMPlus 也能夠獲得 10 分,同樣是 XML 格式。

    JDynamiTe, Fastm, Rife 能夠獲得 5 分。

    JSP, Velocity, Freemarker 只能獲得 0 分。

    (4) Replacement Flexibility 替換靈活度

    主要是指能否自由替換 Template 里面的任何一塊文本。不用考慮 DOM Node

    JSP, Freemarker, Velocity, Rife, JDynamicTe, Fastm 無疑是勝利者,毫無限制,能夠獲得 10 分。

    Taglib, XSL, Tapestry, Wicket, XMLC, DOMPlus 都或多或少受到 DOM Node 的限制(解析的最小單位是 XML Node ),能夠獲得 6 分。

    (5)WYIWYG 所見即所得

    Template 能夠在 Browser 里面直接大致正確顯示,設計人員友好。

    XMLC, DOMPlus 得分 10

    Wicket 得分 9

    JDynamiTe, Fastm, (Rife 根據情況 ) 得分 8

    Tapestry 得分 7 HTML 畢竟夾雜了 Logic Tag

    JSP, Freemarker, Velocity, Taglib, XSL 得分 0

    ?

    Freemarker, Velocity 屬于按行解析,有可能采取如下手段,把語句包含在 XML Comment 里面,進行顯示友好的處理。這種情況下得分 5

    <!--

    #if ….

    -->

    ?

    由于 Taglib XML 規范格式,使得某些 IDE Plugin DreamWeaver Plugin 能夠顯示 HTML Display Taglib 。如果是對于此類 Plugin 來說, Taglib 的所見即所得分數可以是 0-- 5 分。類似于 Tapestry ,仍然是 Logic Tag 影響了最終得分。

    (6)Action Code Purity 用戶代碼純凈度

    主要是指用戶提供顯示數據的后臺 Java 代碼的純凈度,是否免除了 HTML ,或者 Template 操作的污染。

    Servlet HTML 污染現象就非常嚴重。代碼里面夾雜了大量的 HTML Text 。分數自然是 0

    JSP, Freemarker, Velocity 都能夠獲得 10 分。用戶后臺代碼十分純凈,不需要引入具體框架的代碼。任何一份 Action Code ,完全不用知道自己使用的是什么 Template ,這三種 Scripted Template 都能夠隨意替換。能夠獲得 10 分。 pojo

    Taglib 根據各種具體情況,能夠最高獲得 8 分。

    Fastm, DOMPlus 需要根據一定的約定,產生 POJO 數據。用戶 Action Code 同樣不需要引入具體的框架代碼,產生的這些數據同樣可以很容易地被其他 Template ,比如 JSP, Freemarker, Velocity 使用,能夠某種程度上替換 Template 。能夠獲得 6 分。

    Tapestry 需要在每份用戶 Action Code 里面引入 Template 框架的 Package 。只能獲得 4 分。

    Wicket 不僅需要在每份用戶 Action Code 里面引入框架的 Package ,還需要引入框架特殊的 View Data Model 數據類型,并且提供特殊類型的數據。只能獲得 2 分。

    XMLC, Rife, JDynamiTe 不僅需要在每份用戶 Action Code 里面引入框架的 Package ,而且需要大量的 Template 操作。只能獲得 0 分。

    ?

    (這項特性的比較,對于 Tapestry Wicket 來說是不公平的。因為它們的框架就包括了 Template 本身。 Action 里面引入框架 Package 是很正常的。而且這些框架同樣可以外接其余的 Template ,只是原來的編程模型,需要做一些更改。這里只是對于單項比較就事論事。)

    (7) Infrastructure Code Purity 基架代碼純凈度

    這里是指框架的內部實現代碼里面是否夾雜了 HTML Text 污染。這也意味著如果用戶需要擴展頁面 UI 組件,是否也需要在代碼里面夾雜 HTML Text

    HTML Taglib, Wicket, Tapestry 的框架實現代碼里面包含了很多 HTML Text 輸出語句。用戶需要自定義擴展頁面 UI 組件,也需要在代碼里面夾雜 HTML Text 。所以,得分只能是 0

    JSP, Freemarker, Velocity, XMLC, XSL, Rife, JDynamiTe, Fastm, DOMPlus 得分都是 10

    (8) 動態 Include

    即運行的時候,動態選擇 Include 另外的 Template 文件。

    JSP 文件里面的 @ include 屬于靜態 Copy And Paste 技術。

    Jsp:include 命令是動態 Include 相當于

    <%?

    request.getRequestDispatcher(…).include(request, response);

    %>

    這才是動態 Include 技術。

    ?

    Velocity, Freemarker #Parse 指令應該也是動態解釋執行的。也可以算是動態 Include

    至于 XMLC, Rife, JDynamiTe 這類技術能夠隨意操作 Template Node ,動態 Include 也是小菜一碟。

    Fastm, DOMPLus 同樣提供了操作 Template Node 的能力,而且為了避免這類 Template Manipulation 代碼污染,還提供了類似于 XSL Node Interceptor 的機制實現動態 Include

    XSL Apply Imports Call Template 能夠動態引入并使用其他的 XSL

    ?

    所以, JSP, Freemarker, XMLC, Rife, JDynamiTe, Fastm, DOMPlus, XSL 的動態 Include 方面的分數都是 10

    其余的, Taglib, Wicket, Tapestry 得分為 0

    (9)Recursive Display of Tree Data 樹型數據的遞歸顯示

    遞歸顯示一個任意深度的樹型數據,這是一個動態 Include 基礎上的更高級的需求。可以說,不支持動態 Include ,就不支持遞歸顯示。

    遞歸, XSL 無疑是天生贏家。 XSL Pattern Match 語法可以說就是為遞歸編寫的。

    其余的語法都是 Imperative Programming 。遞歸的前提是必須能夠定義一個方法,自己直接或者轉彎抹角的能夠調用到自己。

    對于 JSP, Velocity, Freemarker 這類沒頭沒尾的 Script 來說,屬于強人所難。

    Tapestry, Taglib, Wicket 比較牛,專門提供了 Tree Model

    XMLC, Rife, JDynamiTe 這些 Template Manipulator 高興了,可以在 Java 代碼里面任意根據數據任意操作 Template Node

    Fastm, DOMPlus 不僅可以在 Java 代碼里面任意操作,而且提供了類似于 XSL Pattern Match Node Interceptor 功能,不需要寫 Template Node 操作代碼,就可以實現遞歸。而且可以實現 Data Iterator + Template Iterator 的匹配序列。

    ?

    遞歸方面,得分如下。

    XSL, XMLC, Rife, JDynamiTe, Fastm, DOMPlus 得分 10

    Tapestry, Taglib, Wicket 能夠顯示特定的 Tree Model 。得分 4

    其余的,得分 0 。只能通過 Java 代碼里面夾雜一堆的 HTML Text ,然后整體輸出給 Scripted Template 來實現。

    (10) Space Efficiency 空間效率

    基于 Template Manipulation 的技術都有空間效率問題。用戶同時訪問同一個 Page 的時候,內存中存在多個副本。 XMLC 的問題可能最重。因為 XML DOM 結構很重。

    JDynamicTe, Rife 直接在一個 Template Node 上操作,如果有多個用戶同時訪問同一個 Page 。那么同一份 Template Node 就會在內存中 Duplicate 多份。

    ?

    空間效率方面得分情況

    XMLC 得分 0 JDynamicTe, Rife 得分 3 。如果靜態文本節點作了優化,分數可能更高。

    Taglib 由于編譯的結果非常臃腫, Tag 之間的信息交流非常困難。分數為 6

    DOMPlus 一份 DOM 產生多份 SAX Event ,沒有嚴重的多副本問題,但是 DOM 結構本身比較大,所以得分為 6

    其余的技術,內存里的靜態文本都只保存一份,都沒有嚴重的空間效率問題,得分都是 10

    (11) Mapping Explicitness 映射關系明顯度

    什么數據應該顯示在什么位置,一目了然。這種特性。

    JSP, Velocity, Freemarker 直接在 Template 里面把數據取出來顯示,一目了然,清清楚楚,得分都是 10

    Wicket 的強制 View Model 類型這里幫了大忙,無時無刻不提醒用戶 Model View (Template) 之間的映射關系。得分 8

    XMLC 直接操作 HTML Node By ID, or By Generated Method, 得分為 7

    比起, JSP 等來說, Taglib 的映射關系就隔了一層。尤其是當 Tag 之間存在層次關系的時候,比如, Form Tag 下面的 Input Tag Select Tag 下面的 Option Tag Taglib 的分數只有 6

    XSL XPath Pattern Match 也是要稍微轉個彎,類似于 AOP Interceptor 的思路。得分為 5

    Tapestry 的配置如此復雜,得分只有 4

    Rife, JDynamicTe 直接操作 Template Node ,而且是自定義層次的 Template Node ,用戶編寫 Action Code 的時候,必須隨時查看 Template 里面的那些自定義標簽之間的層次關系,并完全理解,了然于胸,才可能編寫正確的代碼。這方面的成本大大提高。分數只有 3

    Fastm, DOMPlus 的問題類似,也是自定義層次的 Template Node ,需要隨時查看 Template 里面的那些自定義標簽(或者 DOM Attribute )之間的層次關系。分數只有 3

    ?(12) Display Logic Reusability 顯示邏輯重用度

    嵌在 Template 里面的 Server Side Script 代碼,不具有任何可重用性。除了整個 Include ,你無法在另外的地方調用 Template 里面的某一段代碼。

    JSP, Velocity, Freemarker, Logic Taglib, Tapestry Logic Tag XSL 的邏輯可重用度分數都是 0 。當頁面設計人員更改了具體頁面布局元素( HTML Tag )的時候,原來的 Template 里面的 Script 全部作廢,需要重新填充到新的 HTML 里面。

    Template Manipulation Model Match 技術的顯示邏輯都存在后臺的 Java 代碼里面,自然是可以重用的。方法調用,類繼承,包含,怎么都行。

    ?

    Wicket View Model 都是綁定到具體的 HTML UI Tag 上,比如, List, Table 等。當這些 Tag 變化較大的時候,原有的代碼都需要改變。某些 HTML Display Taglib 也是如此。重用度分數為 4

    當結構層次沒有變化,只是具體的 HTML Tag 變化的時候, XMLC 的原有 DOM 處理代碼幾乎不需要變動。在處理循環的時候,代碼需要 Create Specific HTML DOM Node ,然后添加到某個 DOM Node 上面。而且代碼可能大量使用自動產生的代碼的方法。這影響了它的得分,分數為 4

    當結構層次沒有變化,只是具體的 HTML 布局元素發生了變化,那么, Rife, JDynamiTe, 的代碼都不需要變化。但是,它們的代碼侵入性非常強,比 XMLC 還要強(如果 XMLC 采用標準的 HTML DOM 操作方法)。權衡考慮, Rife, JDynamiTe 的重用度分數是 5

    當結構層次沒有變化,只是具體的 HTML 布局元素發生了變化, Fastm, DOMPlus 的代碼也不需要變化。而且, Fastm, DOMPlus 沒有代碼侵入性,產生的 Data Model 就是 POJO ,可以用在 JSP, Velocity, Freemarker Taglib 里面。所以,重用度分數為 8

    Scripted Template

    前面講述了評估指標。下面分別各項技術進行單項說明。

    (1) Scripted Template

    HTML Server Side Script 混雜在一起的顯示層技術。

    包括 JSP, Velocity, Freemarker, Taglib, Tapestry, XSL 等。

    ?

    Server Side 的這些 Scripted Template 技術比較流行,耳聞能詳。前面進行指標描述的時候,各種參數,也基本上涉及到了。就不具體展開進行單項的用法說明和特性分析。

    JSP, Velocity, Freemarker 的優勢在于這些技術對用戶后臺 Java 代碼侵入性非常低,這些 Template 都可以任意替換,而不影響用戶后臺 Java 代碼。

    ?

    下面講述另外兩類不是很常見的技術。

    (2)Template Manipulation

    Java 代碼直接操作 Template (比如, HTML DOM )產生結果的顯示層技術。

    包括 XMLC, JDynamiTe, Rife 等。

    ?

    (3) Model Match

    Java 代碼負責提供符合顯示層要求的 Data Model ,顯示層框架本身把 Data Model Template 進行匹配,產生結果。

    包括 Wicket, Fastm, DOMPlus, 等。

    Template Manipulation

    Java 代碼直接操作 Template (比如, HTML DOM )產生結果的顯示層技術。

    包括 XMLC, JDynamiTe, Rife 等。

    這類技術都具有良好的所見即所得特性。

    (1)XMLC

    http://xmlc.enhydra.org/

    XMLC 把一個 HTML 文件翻譯成一個 Java HTML DOM Class

    比如,

    <INPUT ID="nameInput">

    <TITLE id="title">Hello, World</TITLE>

    <SPAN id="para1">...</SPAN>?...

    這些具有 id HTML 元素,在 Java HTML DOM Class 都產生了對應的方法。

    HTMLElement getElementPara1()

    public void setTextPara1(String text)

    HTMLTitleElement getElementTitle()

    HTMLInputElement getElementNameInput();

    ?

    比如, <INPUT NAME="myName"> CLASS="class1 class2">

    就產生了如下的 Constant Fields.

    ?? public static final String NAME_myName;

    ?? public static final String CLASS_class1;

    ?? public static final String CLASS_class2;

    ?

    具體操作代碼如下,

    HTMLObject htmlObj = new HelloHTML();

    // Construct head

    HTMLHeadingElement head = htmlObj.createElement("h1");

    Text headText = htmlObj.createText("Hello World");

    head.appendChild(htmlTest);

    ?

    // Construct anchor

    HTMLAnchorElement anchor = htmlObj.createElement("a");

    anchor.setHref("Welcome.po");

    Text anchorText = htmlObj.createText("Welcome Page");

    anchor.appendChild(anchorText);

    ?

    // Replace contents of id-labeled node.

    Element replace = htmlObj.getElementReplaceme();

    Element parent = replace.getParent();

    ?

    // Start with the last new child so we can use insertBefore

    parent.replaceChild(anchor, replace);

    parent.insertBefore(head, anchor);

    ?

    可以看到,用戶的 Action Code 里面充滿了 HTML DOM Node 的添加刪除操作。而且里面使用的代碼都不是標準的 DOM 操作方法,而是代碼生成的方法。代碼侵入性非常強,如果要換成別的 Template ,比如 JSP, velocity 所有的代碼都要作廢。

    當然 XMLC 產生的是一個 DOM ,后面還是可以接續 XSL 的。

    ?

    一般來說, XML DOM 操作只能針對完整的 Node 。一般需要替換整個 Attribute ,整個 Text

    對于, <a href=”http://www.mydomain.com/mymodule/{id}.html” 這類只需要替換某一部分的 Attribute 來說,處理起來就有點大而無當。這時候, XMLC 引入了外部的 Regular Expression Matcher 等工具來處理這種情況。

    另外有一個不常見的需求。動態替換 Java Script 代碼的里面的某一部分。這時候, XMLC 就完全無能為力了。或許也可以引入外來的 Text Parser Engine ,比如 Velocity, Freemarker, Fastm, JDynamicTe 等來做這件事情。

    ?

    XMLC 的主要問題還是空間效率問題。每次請求,用戶需要產生一個 Java DOM Class 副本,進行操作。如果有多個用戶訪問同一個 Page ,那么就同時存在多個 Java DOM Class 副本。

    當然里面的靜態文本資源是共享的,我們看到上面的 Java DOM Class 里面,產生了很多 String 常數。

    但是 DOM Node 結構本身的尺寸就比較大。即使采用了一些優化簡化的 DOM Parser ,去除了用不到的結構,整個尺寸還是比較大。

    (2) JDynamiTe

    http://jdynamite.sourceforge.net/doc/jdynamite.html

    ?

    JDynamiTe PHPLib Template 的移植。采用 XML Comment 的方式標記動態結構塊。

    我們來看一個典型的兩層循環的例子。 <tr><td>

    ?

    <table border=1>
    <!-- BEGIN DYNAMIC : myBigRow -->
    <tr>

    <!-- BEGIN DYNAMIC : colX -->
    <td>{VALUE_X}</td>
    <!-- END DYNAMIC : colX -->

    <!-- BEGIN DYNAMIC : colY -->
    <td bgcolor="#33CCFF">{VALUE_Y}</td>
    <!-- END DYNAMIC : colY -->

    </tr>
    <!-- END DYNAMIC : myBigRow -->
    </table>

    ?

    對應的代碼是,

    import cb.jdynamite.*;

    ?

    dynamiTe=new JDynamiTe();

    dynamiTe.setInput(application.getRealPath("cbtemplate/testTemplate.html"))

    ??? // Second table with nested Dynamic Element
    ??? for (int row = 0; row < 5; row++) {
    ??????? // first group of columns
    ??????? // 4) Use "setDynElemValue" to set or reset the value of a Dynamic Element
    ??????? dynamiTe.setDynElemValue("colX", ""); // reset for each row
    ??????? for (int col = 0; col < 3; col++) {
    ??????????? dynamiTe.setVariable("VALUE_X", "line_" + row + ",col_" + col);
    ??????????? dynamiTe.parseDynElem("colX"); // add a column
    ??????? }
    ??????? // second group of columns
    ??????? dynamiTe.setDynElemValue("colY", ""); // reset for each row
    ??????? for (int col = 3; col < 5; col++) {
    ??????????? dynamiTe.setVariable("VALUE_Y", "line_" + row + ",col(BIS)_" + col);
    ??????????? dynamiTe.parseDynElem("colY"); // add a column
    ??????? }
    ??????? dynamiTe.parseDynElem("myBigRow"); // add a row
    ??? }

    ??? // 5) Use "parse" to finaly get the value of your Dynamic Template Document
    ??? dynamiTe.parse();

    ??? out.println(dynamiTe.toString()); // send HTML page

    ?

    我們看到, Template 本身操作貫穿程序的始終。

    setDynElemValue, setVariable, parseDynElem, parse 都是 template Class 本身的方法,類似于 XML DOM Node 的添加刪除修改。

    我們看到這類 DOM Manipulator 的代碼侵入性非常強,用了之后,如果要換別的 Template ,比如 JSP, velocity ,這段代碼完全作廢。

    (3) Rife

    http://rifers.org/

    類似于 JDynamiTe Rife 也采用自定義動態塊標簽。

    下面是一個典型的例子。遞歸顯示一個 Data Tree 。下面只是核心片斷。如果對整個例子感興趣,可以去 Rife 的網站查看 Sample Tutorial

    這是一段 Tree Template

    <body>

    ${v level/}

    ${b level}

    ? <ul>${v nodes/}</ul>

    ${/b}

    ${b node}

    ? <li>${v title/}${v level/}</li>

    ${/b}

    </body>

    ?

    對應的 Java 代碼操作 Template Node, 輸出 Data Tree

    ?

    import com.uwyn.rife.engine.Element;

    import com.uwyn.rife.template.InternalValue;

    import com.uwyn.rife.template.Template;

    ?

    // obtain an instance of the template that will output the tree

    Template template = getHtmlTemplate("tutorial.recursion");

    // obtain a new internal value to construct a collection

    // of sibling child nodes in the local scope

    InternalValue?? nodes = template.createInternalValue();

    // set the child's title value

    template.setValue("title", encodeHtml(child.getTitle()));

    // and append it to the local internal value

    nodes.appendBlock("node");

    // set the level value which includes the sibling nodes in the

    // same level

    template.setBlock("level", "level");

    ?

    我們看到, template 的操作代碼貫穿整個程序的始終。 getHtmlTemplate, createInternalValue, setValue, appendBlock, setBlock 。非常類似于上面 JDynamiTe 的用法。

    JDynamiTe 顯示 Data Tree 的過程也是大致如此。 XMLC 也是如此。

    Rife 同樣具有 JDynamiTe XMLC 的代碼侵入性強的缺點。如果需要換別的 Template 技術,比如 JSP, velocity ,整個代碼都要做廢。

    Model Match

    Java 代碼負責提供符合顯示層要求的 Data Model ,顯示層框架本身把 Data Model Template 進行匹配,產生結果。

    包括 Wicket, Fastm, DOMPlus, 等。

    這類技術都具有良好的所見即所得特性。

    (1) Wicket

    http://wicket.sourceforge.net/

    Wicket 類似于 Tapstry ,采用 HTML 自定義 Attribute 作為自定義標簽。

    這段是 Rife 的一個典型的循環的例子。 wicket:id 一個標簽,幾乎可以滿足任何需求。有興趣的讀者可以去 Wicket 網站查看完整的 Sample 。這里只有核心片斷。畢竟,本文不是一部 Wicket 教程。

    ?

    <html>

    <body>

    ? <form wicket:id = "commentForm">

    ??? Add your comment here:

    ??? <p>

    ??? <textarea wicket:id = "text">This is a comment</textarea>

    ??? <p>

    ??? <input type = "submit" value = "Submit"/>

    ? </form>

    ? <p>

    ? <span wicket:id = "comments">

    ??? <p>

    ?????? ??? <span wicket:id = "date">1/1/2004</span><br>

    ?????? ??? <span wicket:id = "text">Comment text goes here.</span>

    ?????? </p>

    ? </span>

    ? <wicket:remove>

    ??? <p>

    ?????? ??? 1/2/2004<br/>

    ?????? ??? More comment text here.

    ??? </p>

    ? </wicket:remove>

    </body>

    </html>???????????????????????

    ?

    我們可以看到, Template 非常干凈。只有少數的自定義 attribute, (and tag)

    對應的 Java 代碼如下。

    ?

    import wicket.markup.html.WebPage;

    import wicket.markup.html.basic.Label;

    import wicket.markup.html.basic.MultiLineLabel;

    import wicket.markup.html.form.Form;

    import wicket.markup.html.form.TextArea;

    import wicket.markup.html.list.ListItem;

    import wicket.markup.html.list.ListView;

    import wicket.model.PropertyModel;

    ?

    public final class GuestBook extends WebPage

    {

    ?????? /** Use a Vector, as it is synchronized. */

    ?????? private static final List commentList = new Vector();

    ?????? private final ListView commentListView;

    ?

    ?????? public GuestBook()

    ?????? {

    ????????????? add(new CommentForm("commentForm"));

    ????????????? add(commentListView = new ListView("comments", commentList)

    ????????????? {

    ???????????????????? public void populateItem(final ListItem listItem)

    ???????????????????? {

    ??????????????????????????? final Comment comment = (Comment)listItem.getModelObject();

    ??????????????????????????? listItem.add(new Label("date", comment.date.toString()));

    ??????????????????????????? listItem.add(new MultiLineLabel("text", comment.text));

    ???????????????????? }

    ????????????? });

    ?????? }

    }

    ?

    我們看到, Wicket 的代碼,相當干凈利索,雖然寫法上使用了匿名內部類。沒有任何 Template 本身的操作。只是需要提供一個框架需要的 View Model ListView MultiLineLabel Label

    Wicket PropertyModel 能夠用來包裝一個 POJO 。比如,一段 HTML Template

    Stock of IBM: <span wicket:id="stockIBM">some value</span>

    ?

    對應的 Java 代碼是

    import wicket.model.PropertyModel;

    ?

    public PojoStockQuotePage()

    {

    ??? StockQuote quote = new StockQuote("IBM");

    ??? add(new Label("stockIBM", new PropertyModel(quote, "quote"));

    }

    ?

    我們看到, Wicket 的代碼結構非常像 Swing 。只需要對應 HTML UI Tag 提供一份 View Model 就可以。操作起來實在是方便。而且 HTML Tag 里面只需要添加 Wicket:id 這樣的自定義 Attribute ,就可以同時表達動態層次塊和變量部分(其實 Rife 也是如此)。

    ?

    當需要換 Template 的時候,比如 JSP, Velocity, Freemarker Taglib 等, Wicket 提供的 View Model 還是可以使用的。

    Wicket 的一個不足之處是,代碼需要使用框架自定義的 HTML View Model 。這也可能是一個優點,能夠幫助用戶清楚地理解,代碼和 HTML Template 之間的對應關系。

    ?

    從嚴格意義上來說,比起 Taglib, Tapestry 來說 , 只有 Wicket, Echo 這樣的框架才是真正意義上的組件框架。而且, Wicket 相對于 Echo 的優勢如此明顯,這里就不多說了。不然就跑題了。總之, Wicket 是一個非常值得關注的框架。

    (2) Fastm

    http://fastm.dev.java.net/servlets/ProjectDocumentList

    Fastm 的思路相當于 JDynamiTe, Wicket 的思路組合。

    Fastm = JDynamiTe + Wicket

    Fastm 采用自定義標簽來標記動態 Block ,然后類似于 JSTL, Velocity, Freemarker, Tapestry 那樣,接受一個 POJO 作為 Model ,并采用 OGNL Style( 同時也接受 XPath Style) 的方式對數據進行尋址。

    Fastm 的公式很簡單, Fastm Template + Model = Result

    這個 Model POJO 。可以是 Java Bean, Map, DOM Node 等任何 Object

    ?

    我們來看一段典型的 Tree Data 遞歸顯示的例子。

    這段是 HTML Template 片斷。

    ?

    class name: <input type="text" value="{name}">

    <!-- BEGIN DYNAMIC: @children -->

    <ul>

    <!-- BEGIN DYNAMIC: children -->

    ? <li>

    ??? class name: <input type="text" value="{name}">

    ??? <!-- BEGIN DYNAMIC: @children -->

    ??? <ul>

    ??? <!-- BEGIN DYNAMIC: children -->

    ??? <!-- END DYNAMIC: children -->

    ??? </ul>

    ??? <!-- END DYNAMIC: @children -->

    ? </li>

    <!-- END DYNAMIC: children -->

    </ul>

    <!-- END DYNAMIC: @children -->

    ?

    上面的 @children 需要特別說明一下,意思是檢測當前 Model 是否具有 children 這個 property ,如果具有,那么向下展開,否則就跳過去。這樣的話,如果沒有 children 的話,多余的 <ul> tag 就不需要打印出來了。雖然空 <ul>tag 并不影響顯示。

    ?

    對應的 Java 代碼只需要提供一個 POJO 作為 Tree Data

    ?

    ??? public Object makeModel(){

    ?????? Map a = new HashMap();

    ?????? a.put( "name" , "A" );

    ?????? List aChildren = new ArrayList();

    ?????? a.put( "children" , aChildren);

    ?????? {

    ?????????? Map a1 = new HashMap();

    ?????????? a1.put( "name" , "A1" );

    ?????????? List a1Children = new ArrayList();

    ?????????? a1.put( "children" , a1Children);

    ?????????? {

    ????????????? Map a11 = new HashMap();

    ????????????? a11.put( "name" , "A1-1" );

    ????????????? a1Children.add(a11);

    ?

    ????????????? Map a12 = new HashMap();

    ????????????? a12.put( "name" , "A1-2" );

    ????????????? a1Children.add(a12);

    ?????????? }

    ?????????? aChildren.add(a1);

    ?????? }

    ?????? return a;

    ??? }

    ?

    這段代碼采用了 Map 作為 Model, 也可以采用 Java Bean, XML DOM Node 等任何 Object 。所以,當然可以提供一個 XML 文件作為 Model

    ?

    看起來 Fastm JSP, Freemarker, Velocity JSTL 一樣,對 View Model 沒有什么特殊要求。 POJO 就可以。基本上就是如此。

    且慢, Fastm Model 還是有特殊要求的。類似于 Wicket Fastm 也沒有邏輯標簽, Fastm 也利用數據來表示條件、循環等邏輯分支。遇到 Collection, Array 等數據類型,就自動把動態塊展開。如果不顯示某一塊,那么就提供一個空數據。

    這就是 Fastm 所需要的所有約定。看起來很簡單,真正滿足這個約定也不難。但是,某些特殊的情況下,為了滿足這個約定,需要后臺的用戶代碼做一些比 JSP, Velocity, Freemarker 要求的更多的 Model 組裝工作。

    Fastm 的另一個問題是, Model View Template )之間的映射關系不是很明了。雖然比 JDynamiTe Rife 等容易明白多了,但是比 Wicket 還是差一些。因為 Fastm 沒有自定義 View Model 類型,需要用戶自己掌握 Bean, Map 層次和 Template 層次之間的正確對應。

    (3) DOMPlus

    http://fastm.dev.java.net/servlets/ProjectDocumentList

    DOMPlus Fastm 的思路在 XML DOM 領域的擴展。

    如果說, Fastm = JDynamiTe + Wicket ;那么, DOMPlus = XMLC + Wicket

    DOMPlus XMLC Wicket 思路的組合。

    如果說, Fastm 的公式是, Fastm Template + Model = Result

    那么, DOMPlus 的公式是, DOM + Model = DOM or SAX

    這個 Model POJO 。可以是 Java Bean, Map, DOM Node 等任何 Object

    一個很有趣的現象就是 DOM + DOM = DOM

    沒錯,就是如此。

    ?

    DOMPlus 采用自定義 DOM Attribute 來標記動態 Element, 動態 Attribute, 動態 Text

    我們來看一個典型的 Tree Data 遞歸顯示的例子。

    對應的 HTML DOM 片斷是。

    ?

    ? <li nodeTarget = "child">

    ??? class name: <input type="text" attributesTarget="value=@name" />

    ??? <ul>

    ??? <li nodeTarget = "child" />

    ??? </ul>

    ? </li>

    ?

    nodeTarget 表示可能被重復多次的動態 Element attributesTarget 表示需要替換的 attribute 。這里數據尋址方式采用的是 XPath @name 表示 DOM Node name attribute

    DOMPlus 的自定義標簽只有 3 個, nodeTarget, attributeTarget, textTarget

    ?

    對應的 XML Tree Data 是,

    ?

    <data name="topClass">

    <child name="A">

    ? <child name="A-1">

    ??? <child name="A-1-1"/>

    ? </child>

    ? <child name="A-2">

    ??? <child name="A-2-2">

    ????? <child name="A-2-2-3" />

    ??? </child>

    ? </child>

    ? <child name="A-3"/>

    </child>

    <child name="B">

    ? <child name="B-1" />

    </child>

    <child name="C" />

    </data>

    ?

    這兩個 DOM 一匹配,就產生了結果 XML ,是一棵顯示在 HMTL List 里面 Tree

    ?

    DOMPlus Template 更加干凈,幾乎接近于 XMLC Pure HTML DOM ,等同于 Wicket

    而且 DOMPlus 并沒有 XMLC 的空間問題。 DOMPlus 只保留一份 DOM 在內存中,每次請求來的時候, DOMPlus 根據數據匹配產生 SAX Event ,直接寫入 Response

    ?

    DOMPlus 的匹配引擎很類似于 XSL 的功能,同樣是用 XML 格式的模板文件處理 XML 數據。而且兩者都同樣是遞歸處理引擎。

    所不同的是 DOMPlus Template 能夠在瀏覽器中正確顯示,而且表達結構的自定義屬性非常簡單,只有 3 個( Fastm 2 個)。

    ?

    DOMPlus 的問題和 Fastm 一樣,數據層次和模板層次之間的關系,一定要非常清楚,而不是像 JSP, Velocity, Freemarker 那樣把數據抓過來就可以用。

    另外的問題就是,處理的最小單位是 XML Node XML Node 里面的 text 的部分替換就無能為力了。比如 <a href=”http://www.domain.com/module/{id}.html”

    XMLC 的解決方法一樣,可以引入外面的文本解析器。用來處理 XML Node 鞭長莫及的地方,比如, JavaScript 代碼的內部的動態替換部分。

    Regular Expression Velocity, Freemarker, Fastm, JDydanamiTe ,等任何能夠脫離 Web 環境的通用文本解析工具都可以。 JSP, Taglib, Tapestry, Wicket 等無法脫離 Web 環境而存在,肯定不行。

    ?

    ------

    注:

    Fastm DOMPlus 是我的作品,輕量的 Template 匹配引擎。這兩項技術本身只是單項的 Template 顯示技術,不是一個完整的 web 整體解決方案。

    特性總表

    (1) Host Language Consistency 宿主語言一致性

    (2)Template Purity 模板純凈度

    (3)Template Tidiness 模板整潔度

    (4) Replacement Flexibility 替換靈活度

    (5)WYIWYG 所見即所得

    (6)Action Code Purity 用戶代碼純凈度

    (7) Infrastructure Code Purity 基架代碼純凈度

    (8) 動態 Include

    (9)Recursive Display of Tree Data 樹型數據的遞歸顯示

    (10) Space Efficiency 空間效率

    (11) Mapping Explicitness 映射關系明顯度

    (12) Display Logic Reusability 顯示邏輯重用度

    ?

    限于空間,下面的分數表采用索引數字來代表特性。橫向是特性,縱向是技術。

    下面的表格中沒有寫 Freemarker ,只寫了 Velocity ,這兩項技術比較類似。各項參數也大致接近。當然,各自的 Fans 都能夠看到很深很細的使用細節,宏定義之類的。

    ?

    指標索引

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    Scripted Template

    Velocity

    2

    0

    0

    10

    0-5

    10

    10

    10

    0

    10

    10

    0

    JSP

    10

    0

    0

    10

    0

    10

    10

    10

    0

    10

    10

    0

    Taglib

    0

    0

    10

    6

    0-5

    2 - 8

    0

    0

    4

    6

    6

    0

    Tapestry

    0

    0

    10

    6

    7

    4

    0

    0

    4

    10

    4

    0

    XSL

    10

    0

    10

    6

    0

    10

    10

    10

    10

    10

    5

    0

    Template Manipulation

    XMLC

    5

    10

    10

    6

    10

    0

    10

    10

    10

    0

    7

    4

    JDynamiTe

    5

    8

    5

    10

    8

    0

    10

    10

    10

    3

    3

    5

    Rife

    5

    3-7

    5

    10

    0-7

    0

    10

    10

    10

    3

    3

    5

    Model Match

    Wicket

    5

    9

    8

    6

    9

    2

    0

    0

    4

    10

    8

    4

    Fastm

    5

    7

    5

    10

    8

    6

    10

    10

    10

    10

    3

    8

    DOMPlus

    5

    9

    8

    6

    10

    6

    10

    10

    10

    6

    3

    8

    ?

    ?

    下面我們大致看一下 Browser Side Ajax )的情況。

    Browser Side

    Server Side 的技術格局恰好相反, Browser Side HTML DOM Manipulation 技術、 HTML View Model 技術比較多,比較流行。各種 JavaScript UI 控件, DOM 綁定控件,這方面的庫很多,而且很酷。這里不再列舉了。

    ?

    Browser Side Scripted Template 技術就比較少見了。我知道的大概有下面幾個。

    ?

    TrimPath JST

    http://www.trimpath.com/project/wiki/JavaScriptTemplates

    語法舉例

    <option value="${country.name}" {if country.name == currCountry}selected{/if}>

    ?

    ?

    Helma

    http://dev.helma.org/Wiki/JavaScript+Template+Engine/

    語法舉例

    ? <% if (session.user != null) %>

    ??? Hello <%= session.user.name %>

    ? <% else %>

    ??? <a href="/login">Login</a>

    ? <% end %>

    ?

    SWATO

    http://swik.net/SWATO/Swato+JavaScript+Template

    語法舉例

    #for (i in products) {

    #??? var p=products[i];

    ??? <td>$<%p.price%></td><td><%p.quantity%> : <%p.alert%></td>

    ??? </tr>

    #}

    ?

    以數據為中心的 Ajax 應用中(把數據取過來,而不是取一段 HTML ,或者一段 Script ),當頁面布局結構比較復雜的情況下,也可以選擇 Browser Side XSL

    ?

    一個有趣的聯想是 DOMPlus 的思路。

    DOMPlus 不僅支持 DOM + DOM = SAX ,而且支持 DOM + DOM = DOM

    這個特性特別適合于 Browser Side 。假設存在 DOMPlus Javascript 版本。

    Javascript Server Side 拿來 XML Data ,和 Browser 里面的一段 HTML 進行一下 Match ,顯示就搞定了。不需要寫任何代碼。

    Unobtrusive

    Brower Side 方面, Scripted Template 技術并不流行。

    這個事實說明了, Browser Side 的顯示技術更加歸于常態,顯示模型更加自然。

    JavaScript 編程有個流行的概念,叫做 Unobtrusive ,就是我們常說的無侵入性。

    JavaScript, HTML, CSS 清晰有效的分開。

    行為的歸行為,內容的歸內容,風格的歸風格。

    凱撒的歸凱撒,上帝的歸上帝,人民的歸人民。

    各自照看好自己的領域,而不侵入他人的領域。

    ?

    無侵入, POJO 等概念,在 Server Side 方面(比如 Java ),也是甚囂塵上,炒作的不亦樂乎。

    但是在 Web 顯示技術的方面, Unobtrusive 無侵入特性,不能不說, Browser Side 由于先天的 JavaScript 操作 DOM 的優勢,已經走在了前面。

    ?

    雖然 JavaScript 作為一門動態語言,開發效率自然超過強類型編譯語言,但是代碼維護、 IDE 提示、輔助重構方面的成本也不可低估。

    所以, Server Side 的顯示技術,仍然是不可缺少的。在 Server Side 同樣應用 Unobtrusive 原則,也仍然具有重要的意義。

    前面提到的兩個指標, Template Purity 模板純凈度 , Action Code Purity 用戶代碼純凈度。

    就屬于 Unobtrusive 指標。

    ?

    顯示技術里面,代碼邏輯表示動態部分,復雜部分; Template 表達靜態部分,簡單部分。

    所以,人們更加關注代碼邏輯的容易管理的程度。

    由于代碼邏輯在 IDE 里面相對容易管理。人們更能夠容忍 Java 或者 Java Script 代碼里面出現具體的 Template Node ,而覺得 Template 里面的 Script 比較難以管理。

    ?

    Scripted Template 基本上是 Obtrusive 的,對 Template 的侵入性最強。雖然 Template 操作沒有侵入到 Java 或者 JavaScript 代碼。

    這叫做 1 -- Way Obtrusive

    ?

    Template Manipulation 大致能夠做到對 Template Unobtrusive 非侵入,雖然他們的 Template Node 操作侵入了 Java 或者 Java Script 代碼。

    這叫做 1-Way Unobtrusive

    ?

    Model Match 技術具有最好的 Unobtrusive 非侵入特性。 Java 或者 JavaScript 代碼不侵入 Template 到里面,具體的 Template Node 操作也不侵入到 Java 或者 JavaScript 代碼里面。

    這叫做 2-Way Unobtrusive

    ?

    Fastm, DOMPlus 是天生的 Model Match, 具有 2-Way Unobtrusive 特性。

    Wicket 也是天生的 Model Match ,大致能夠做到 1.5 -Way Unobtrusive

    如果嚴格限制不采用 Logic Taglib, Tapstry Logic Tag ,那么 Taglib Tapestry 也能夠做到 1.5 – Way Unobtrusive.

    顯示邏輯 AOP

    這個需求主要包括頁面數據類型的統一格式化。

    比如,所有類型為 Date ,名字以 Time 結尾的數據( startTime, endTime 等),都顯示到秒鐘; Day 結尾的時間字段 (registerDay, birthDay ) ,都顯示到天。 Period, Quarter, Year 結尾的字段也都有不同的顯示需求。

    能夠支持自定義顯示邏輯 AOP Interceptor 的技術并不是很多。

    XSL 語法天生就是 AOP 語法, Declaring Pattern Match ,用法就是要求程序員編寫 Interceptor

    Fastm, DOMPlus 對這方面也支持的很好。同樣是采用自定義 Interceptor

    ?

    W3 DOM Level 2 規范定義了 DOM Traversal

    http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/traversal.html

    DocumentTraversal, TreeWalker, NodeIterator, NodeFilter

    使用 Pull 模型( SAX Push 模型)處理 XML 的程序員,可以使用 NodeFilter 來過濾掉不需要顯示的節點。 NodeFilter 畢竟只是一個 Filter ,只能對 Node 內容進行簡單的開關選項處理, YES, or No ,顯示或者不顯示。只是作為 DocumentTraversal whatToShow 參數的一個補充。 AOP 能力很有限。

    多語言支持的終極解決方案

    多語言支持,也叫做國際化,本地化。

    一般采用字典文件的做法。比如, dict.en, dict.cn, dict.fr, dict.de, dict.jp 等。

    在這類做法里面, Template 里面通常都只有 Message Key

    <span>< message key=”name” /></span>

    ?

    有些更好的做法是這樣,提供缺省文本信息。

    <span id=”key.name”> 用戶名稱 </span>

    ?

    這樣能夠保持頁面的一目了然。

    ?

    除了字典文件的做法之外,另一種做法是直接把文字資源,存放到 Template 里面。

    然后分多個目錄。 En, cn, fr, de, jp 等目錄,下面全都是對應的 Template 文件。

    這種方案叫做語言目錄方案。

    這種方案的缺點很明顯,一個文件的改動,要擴散到所有的對應文件中。

    這種方案的優點也很明顯,文件內容一目了然,尤其是支持所見即所得的模板。另一個優點就是運行效率。字典文件方案運行的時候,需要進行大量的查字典,動態替換文本工作。而語言目錄方案的模板里面大部分都是靜態文本。

    ?

    有沒有一個兩全其美的方案?答案是,有。

    首先,我們采用自己的母語(比如,中文)作為主模板文件,都放在 cn 目錄下。

    然后,其中需要多語言的文本信息,都采用下面這種方式包裝起來。

    <span id=”key.name”> 用戶名稱 </span>

    <p id=”key.help.charpter1”>long text about system help</p>

    ?

    這時候, Template 仍然保持了所見即所得的特性。然后,我們根據這些 Key ,做其他語言的字典文件。 Dict.en, dict.jp, dict.fr, etc.

    然后我們用一個文本處理引擎,替換掉這些多語言信息。為每一種語言產生一個目錄,下面都是對應的語言的 Template 文件。比如, en, jp, fr, Template 文件目錄,里面都是對應的填充了內容的模板。打開一看,一目了然。

    當然,這個處理過程中,并沒有影響那些動態數據部分,而只是替換了靜態文本部分。

    每次只需要更改主要語言目錄的文件,然后用引擎處理,變化自動分布到其他語言目錄。

    這種技術的關鍵在于, Template 本身是否可再生資源?能否被多次處理?能否被統一處理?

    有幾種技術是具有這種可能性的。

    Taglib 理論上可以被當作 XML 文件處理,具有理論上的可行性。

    Fastm, DOMPlus 具有現實可操作性。 Fastm, DOMPlus 都可以自定義標簽,處理動態部分的同時,也能夠忽略其他動態部分。

    總結與展望

    本文分析了 Web 層顯示技術的各類指標和特性。

    本文的討論目前還只是局限于一般的 B/S 結構。

    Web Service, SOA 代表了 Web 未來發展的趨向。數據整合,流程整合,各類資源整合。

    界面 UI 也不會限于 HTML 一種, XUL, XAML, SVG, RSS 等也有各自的應用。

    ?

    我們都知道 Web 中有一種“盜鏈”的現象。

    一個網站,不是通過 Copy ,而是直接通過 Link 引入了其他網站的資源,比如 CSS ,圖片資源等。這樣可以節省自己的 Server 資源。

    有些技術更狠,能夠抓取別人的頁面內容,剪貼拼湊之后顯示在自己的網頁上。

    這種情況實際上是一種偷偷摸摸的不被允許的資源共享實踐。

    ?

    Web Service 把這種實踐發展成了一種商業模式,資源共享模式。不僅可以共享數據和資源,而且可以共享內容和服務(比如 Portlet )。

    比如, Web Service Remote Portal ,就是一種內容提供模式、服務提供模式。網站流量不再依靠用戶點擊率來計算,而是依靠 Web Service 調用率。

    ?

    我們來看看,能夠共享的資源有哪些。

    CSS, 圖片, JavaScript 等可以直接 Link 過來;數據、內容可以抓取過來。

    其中以 CSS 的共享最為流行。 CSS + 圖片 + 某些文字替換,組成了一個 Theme (顯示主體),或者 Skin (表觀)。很多人津津樂道,并孜孜不倦地談論、應用、提供各種 Themes, Skins

    但是還有一個重要的資源共享沒有得到充分的發展。就是 Template Layout 的共享。

    目前, Web Server Template 資源,一般都存放在自己的文件系統中。

    假設這樣一種方式。

    一個 Web Server 運行的時候,通過 Web Service 獲取數據,通過 Link 引用 CSS JS ,圖片等,通過 XLink + XPointer + XPath 獲取一份 XML Node or Fragment or Text ,作為 Template Layout ,自己的服務器上只需要一份 Display Logic 把這些東西組裝起來,就可以把頁面發布出來。甚至 Display Logic 也可以從 Web Service 獲取( Script 等,當然這里面涉及到安全問題),自己只負責統籌管理安排調用。

    這種模型對于 Web Service Client 來說,也是適用的。

    這種模型的關鍵就在于, Unobtrusive 。所有領域都是清楚地分開, Domain Specific ,決不侵入到其他領域,也不允許其他領域的侵入。

    ?

    以上是我對 Web 顯示技術的總結和展望。

    本文到這里結束。

    ?

    posted on 2006-07-14 16:50 buaawhl 閱讀(676) 評論(1)  編輯  收藏

    評論

    # re: Web顯示層技術評估 2008-04-10 13:37 游客
    受益匪淺!  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲av永久无码| 亚洲熟女一区二区三区| 成人免费在线看片| 亚洲免费一级视频| 国产2021精品视频免费播放| 88av免费观看| 日本高清在线免费| 国产精品69白浆在线观看免费| 午夜国产精品免费观看| 国产成人午夜精品免费视频| 成年女人免费视频播放77777| 最近免费中文字幕视频高清在线看| 青青青免费国产在线视频小草| 97免费人妻无码视频| 最近中文字幕mv免费高清电影| 日韩免费福利视频| 免费人成在线观看网站品爱网日本| 亚洲А∨精品天堂在线| 国产亚洲色婷婷久久99精品91| 人人狠狠综合久久亚洲88| 亚洲爱情岛论坛永久| 亚洲沟沟美女亚洲沟沟| 一本色道久久88亚洲精品综合| 亚洲AV噜噜一区二区三区| 夜夜爽妓女8888视频免费观看| 久久最新免费视频| 中文字幕视频免费| 成人在线视频免费| 四虎亚洲国产成人久久精品| 在线观看亚洲天天一三视| 亚洲福利在线视频| 亚洲一区二区三区在线网站| 国产精品自拍亚洲| 亚洲另类少妇17p| 日韩精品视频免费观看| 亚洲成av人在片观看| 亚洲伦理一区二区| 亚洲精品国产av成拍色拍| 亚欧乱色国产精品免费视频| 8x8x华人永久免费视频| 国产美女无遮挡免费视频网站 |