Vincent.Chan‘s Blog

          常用鏈接

          統(tǒng)計

          積分與排名

          網(wǎng)站

          最新評論

          抽取界面 (II):對基本框架的若干擴展

          級別: 初級

          Martin Gerlach, 軟件工程師, IBM Almaden 研究中心

          2001 年 3 月 01 日

          本 文是作者去年 12 月關于 Web應用前端的那篇文章的續(xù)篇。本文介紹對 XML 數(shù)據(jù)和 XSL樣式表基本框架的若干擴展,并將集中討論應用的后端問題,包括國家語言支持(NLS)、視圖結構強化和性能問題。上一篇文章介紹了利用 XML 和 XSLT構建 Web 應用的基本結構,本文介紹在使 Web應用在線運行之前所要做的準備工作。

          本文是系列文章“抽取界面”的第二篇。為了理解本文出現(xiàn)的概念,您不妨讀一下第一篇文章, 用 XML 和 XSL 構建有良好適應性的 Web 應用前端 ,該文討論了完成此應用所必須的步驟。研究此應用樣例的代碼也能幫助您理解本文的概念。與第一篇文章一樣,本文仍假定您已經(jīng)熟悉基于 HTTP 協(xié)議和 HTTP 請求-響應機制的 Web 應用,同時也假定您曾經(jīng)用 HTML、甚或 JavaScript 制作過網(wǎng)頁。您應懂得 Java 編程語言,知道如何將 Java servlet 用作 Web 應用的訪問點。

          已討論過的內(nèi)容

          在第一篇文章中,我介紹了 WebCal,它是一個簡單的、基于 Web 的日歷應用程序,能夠為多個用戶維護日歷。通過這個應用程序,我演示了如何建立一個不僅能夠通過標準 Web 瀏覽器訪問、而且能通過可理解其他格式 ― 例如,WML 和用于語音接口的 VoiceXML ― 的瀏覽器訪問的復雜 Web 應用。那篇文章分三部分討論上述內(nèi)容:

          • 對 XML 數(shù)據(jù)和 XSL 樣式表結構化的一種方法
          • 服務器端的 XSL 轉換 ― 用 XSLT 和 XPath 生成輸出結果
          • 用 XSLT 構建 HTML 表單




          回頁首


          本文的內(nèi)容

          本文也將討論三個主題,但這三個主題并不像第一篇文章討論的三個步驟那樣互相緊密關聯(lián),即它們相互之間不存在特定順序。但每個主題在使 Web 應用在線運行之前的準備工作中都占有重要一席。這三個主題是:

          • 國家語言支持 (NLS):如果面對許多國家的客戶,您將希望提供一個多語言用戶界面。您希望系統(tǒng)自動選擇用戶的首選語言并用該語言顯示與 NLS 相關的信息。
          • 強化應用結構: 通常,Web 應用由許多“視圖”組成。在 WebCal 應用樣例中,視圖或者顯示一個用戶引發(fā)的各種事件,或者顯示新事件的輸入表單。登錄頁和注冊頁也是視圖。視圖可以按不同的標準分組。在 WebCal 中,日視圖、周視圖和月視圖都可以看作是日歷視圖,它們共享同一個子導航 ― 用于輸入新事件的鏈接。將視圖按功能分組,開發(fā)人員就可以避免重復編碼,從而減輕應用開發(fā)工作量,減少錯誤率。
          • 提高性能: 您希望自己的 Web 應用能夠很快作出響應,用戶也不希望點擊一個鏈接后等很長時間。此時,您就會想到使用緩存機制,以更快、更可靠地為用戶提供服務。

          我們先從國家語言支持 (NLS) 著手。如果您對此已經(jīng)很熟悉,則可轉到下一主題, 強化應用結構。





          回頁首


          國家語言支持 (NLS)

          為應用賦予多語言用戶界面的過程 ― 即加入國家語言支持的過程 ― 稱為“國際化”。國際化是 Java 程序的核心問題,因為 Java 通常被設計在任何地方、在任何平臺上、(尤為重要的是)以任何人的語言運行。Java 語言有一系列內(nèi)建的國際化功能,在 developerWorks 上有這方面的文章。

          一般而言,關于 NLS 有兩方面的內(nèi)容:

          • 識別客戶機的首選語言
          • 在應用中的任何地方訪問針對該語言提供的資源

          識別客戶機的首選語言
          就 WebCal 而言(其他 Web 應用也一樣),客戶機可從世界各地方訪問該系統(tǒng)。理想情況下,我們期望以客戶機的首選語言提供用戶界面。主要有兩種方法可用來完成這一任務。

          從 HTTP 請求的 Accept-Language 標頭中可獲得客戶機瀏覽器的語言代碼(例如, en-us 和 de)。該標頭列出了瀏覽器所支持的語言,如清單 1 所示。清單中的第一個值即被作為瀏覽器的(或者說是客戶機的)首選語言。


          清單 1: HTTP Accept-Language 標頭示例
          												
          														
          Accept-Language: en_us;en_ca;de;

          清單 2 中,首選語言是用 HttpServletRequest.getHeader("Accept-Language") 和基本的 Java 字符串操作提取的。

          另一種方法是,我們可以讓 Web 應用的用戶自行選擇首選語言,然后根據(jù)用戶的選擇生成語言代碼。您所要做的就是創(chuàng)建一個網(wǎng)頁,其中含有供用戶選擇首選語言的表單。具體實施細則請參閱 第一篇文章 的步驟 3,“使用表單”。

          用戶首選項與瀏覽器的語言環(huán)境

          通過讓用戶選擇將瀏覽器的語言環(huán)境用作他的語言(或語言環(huán)境)首選項,您就可以將用戶首選項和瀏覽器輸入結合起來使用。這也適用于其它類似的首選項,例如 12 小時制和 24 小時制。

          我們?yōu)槭裁匆芯?HTTP 標頭或用戶首選項的解析過程呢?在獨立的國際化 Java 應用程序中,語言代碼是通過查詢系統(tǒng)獲得的。在查詢過程中, ResourceBundle 類負責為系統(tǒng)語言代碼查找正確的資源。但是,在我們的應用樣例中,用戶的語言(客戶機語言)完全與應用所在系統(tǒng)的語言(服務器語言)無關,我們不得不用一個固定的語言代碼代表用戶的首選語言。

          訪問針對客戶機首選語言提供的資源
          一旦成功地獲得正確的客戶機語言代碼,我們就需要使用固定的語言代碼查找翻譯文本。 清單 3 說明了如何使用清單 2 中的 Locale 對象 locale 完成此項工作。

          在第一篇文章中,我介紹過一個基于 XML/XSL Web 應用框架的應用樣例。在該框架中,我們需要區(qū)分需要 NLS 的兩個不同場所:在 Java 代碼中和在 XSL 樣式表中。

          Java 中的 NLS
          必須在 Java 中完成待顯示文本的 NLS 查找工作。就此處的情形而言,XML 數(shù)據(jù)可以包含待顯示文本 ― 也就是通過 XSL 轉換將 XML 數(shù)據(jù)復制為客戶機所要求的格式。在這種情況下,可以使用 ResourceBundle 類(請參閱 清單 3 )來查找已翻譯好的字符串常量,并將國際化字符串置入 XML 數(shù)據(jù)中。

          XSL 中的 NLS
          有些用戶界面可能需要使用特殊的輸出格式。例如,我們或許不希望在 Web 瀏覽器上和 WAP 電話上顯示完全一樣的輸入域標簽。對 WAP 電話而言,我們可能希望使用很短的標簽,而在 Web 瀏覽器中,標簽就可以長一些,還可以加入幫助內(nèi)容輪翻顯示等功能。在這種情況下,同一個視圖的適用于不同格式的 XSL 樣式表就可以包含不同的文本。在 WebCal 的 XSL 樣式表中,我使用了許多字符串常量: LoginUsername PasswordDayWeekMonth 、本周的每一天,等等。為了將它們國際化,一種方案是實現(xiàn) XSL 中的資源包查找,另一種方案是在 XML 生成期間(即在 Java 中)完成查找,同時把所需的全部翻譯內(nèi)容添加到 XML 文檔中供樣式表使用。

          利用我在 WebCal 中使用過的 James Clark 的 XSL 處理器 XT(請參閱 參考資源 ),上面的兩種方案都能實現(xiàn)。XT 允許回調在 XSL 處理期間訪問處于 classpath 中的任何類的靜態(tài)方法。

          設想我們在 com.ibm.almaden.webcal.WebCalUtils 中有一個靜態(tài)查找方法,如 清單 4所示。

          如果能從 XML 中獲得語言代碼(也就是,如果 Java 代碼已在 XML 生成期間加入語言代碼),您就可以從您的式樣表中調用此方法。另一方面,假如語言代碼已經(jīng)被作為根元素 webcallang 屬性加入 XML 數(shù)據(jù)中,則您也可以使用 清單 5中重點介紹的 XSL 指令完成查找工作。

          為保證此代碼樣例順利工作, lsLookUp()請參閱清單 4 )使用的資源包必須在每個語言文件中定義關鍵字 SUNDAY、MONDAY 等等。盡管可以使用非字符串的數(shù)據(jù)類型在 XSL 和靜態(tài) Java 方法之間傳遞參數(shù),但我建議使用字符串傳遞,以避免過多的轉換開銷。

          國際化的其他方面 除了語言之外,關于 NLS 和國際化還有許多問題。如果您還計劃使用時間、日期、或者貨幣符號,您可能需要使用更靈活的顯示方式和輸入域。

          對于從 XSL 中調用的方法,存在過載能力方面的一些限制。詳細信息請參閱 XT 文檔(請參閱 參考資源)。與在 XML 生成期間完成查找并在 XSL 處理之前將翻譯好的字符串包括在 XML 數(shù)據(jù)中的方法相比較,使用進入 Java 的回調不會產(chǎn)生相同的性能結果。

          NLS 小結
          這一部分詳細分析了國家語言支持問題,說明了如何確定用戶的首選語言以及如何用 Java 或 XSL 樣式表針對這種首選語言執(zhí)行 NLS 查找。

          下面講解如何改進應用結構,以使代碼更易于維護和擴展。





          回頁首


          強化應用結構

          仔細觀察 WebCal 應用樣例,您會注意到所有的日歷視圖不僅共享相同的主導航和通用鏈接(Home 和 Logout),而且還共享包含新事件(New Event)鏈接的相同子導航條。第一篇文章介紹應用樣例時,我認為每個視圖的子導航是互不相同的。

          在復雜的 Web 應用中,您或許需要將視圖按功能分組 ― 例如,分為布局和導航 ― 這樣,您就不必一遍又一遍地為每個視圖進行定義,而且在需要變動時您只需修改一段代碼,無需再修改組中每個視圖的樣式表。這一點在 WebCal 應用樣例中沒有使用,不過分組方法基本上有二種:

          • 在導航元數(shù)據(jù)中定義組
          • 使用XSL 層疊樣式表

          在導航元數(shù)據(jù)中定義組 (WebCal: /web/<format>/navigation.xml)
          觀察 web/html/navigation.xml 中的 navigation.xml 文件,可以發(fā)現(xiàn)日歷視圖的以下 xml 代碼:


          清單 6: 未分組的視圖
          												
          														
          <actions>
          ...
          <action name="ShowDay">
          <sub-nav>
          <link type="internal" text="New Event" href="ShowNewEvent">
          <pass-param name="date"/>
          </link>
          </sub-nav>
          </action>
          <action name="ShowWeek">
          <sub-nav>
          <link type="internal" text="New Event" href="ShowNewEvent">
          <pass-param name="date"/>
          </link>
          </sub-nav>
          </action>
          <action name="ShowMonth">
          <sub-nav>
          <link type="internal" text="New Event" href="ShowNewEvent">
          <pass-param name="date"/>
          </link>
          </sub-nav>
          </action>
          ...
          </actions>

          顯然,這種結構難于維護:如果要為三個日歷視圖添加一個新的子導航鏈接,就必須在所有三個 <action> 元素中添加。如清單 7 所示,通過分組的視圖維護 XML 不是更容易嗎?


          清單 7: 分組視圖
          												<actions>
          ...
          <group name="calendar">
          <sub-nav>
          <link type="internal" text="New Event" href="ShowNewEvent">
          <pass-param name="date"/>
          </link>
          </sub-nav>
          <action name="ShowDay">
          <sub-nav/> <!-- no view specific sub navigation -->
          </action>
          <action name="ShowWeek">
          <sub-nav/> <!-- no view specific sub navigation -->
          </action>
          <action name="ShowMonth">
          <sub-nav/> <!-- no view specific sub navigation -->
          </action>
          </group>
          ...
          </actions>

          這樣一來,您就可以將新的子導航鏈接添加到 <group> 節(jié)點的 <sub-nav> 節(jié)點中,它就會在所有三個日歷視圖中顯示出來。由于只需要在一個地方定義該鏈接,從而提高了結構的可維護性。對本例而言似乎,這似乎沒有帶來什么好處,但實際的 Web 應用要比 WebCal 復雜得多。

          為簡單起見,我們假定分組以后再沒有未分組的視圖。這意味著 navigation.xml 文件中的 <actions> 元素再沒有 <action> 子元素。 <actions> 元素只有 <group> 子元素,后者至少再帶有一個 <action> 子元素。(通常,這表示在 <group> 節(jié)點之外不會有 <action> )。同樣,負責為視圖生成 XML 的 Java 代碼中也要包括包含此視圖(或者 action)的 XML 元素 ― 例如, <groupname>calendar</groupname> ,如清單 8 所示。


          清單 8: 視圖 XML
          												
          														
          <webcal>
          <http-params>
          <param name="action" value="ShowWeek"/>
          <param name="date" value="2001-02-11"/>
          </http-params>

          <groupname>calendar</groupname>
          <user>...</user>
          <navigation> ... </navigation> <!-- groups and actions as shown above -->
          <now date="2000-11-07T15:30"/>
          <week date="2001-02-11" previous="2001-02-04" next="2001-02-18">
          <day date="2001-02-11"/>
          ...
          </week>
          </webcal>


          在第一篇文章的清單 26 中,我介紹過一段為視圖創(chuàng)建子導航鏈接的 XSL 代碼。 清單9 是一段用視圖分組創(chuàng)建子導航的 XSL 代碼,它說明了如何從 XML 數(shù)據(jù)中獲取當前的 action 和 group (如清單 8 所示)。(在該清單中, action 代表 HTTP 的 action 參數(shù)在服務器上觸發(fā)的一些具體操作。每個這樣的操作都生成一個視圖,并會顯示這個顯示。)

          在 WebCal 中,子導航是區(qū)分視圖和組的唯一導航標準,但更復雜的應用可能會有若干個由分組機制處理的參數(shù)。另外一種分組機制要使用 XSL 層疊樣式表。

          XSL 層疊樣式表
          <xsl:include> 除了在導航元數(shù)據(jù)中完成分組外,還可以在樣式表中用于控制主面板 (main panel)(例如, WeekViewMain.xsl )。這樣,某個組的視圖樣式表就會包括該組中所有視圖使用的 XSL 模板。這就好比許多 Java 方法調用一個工具方法。第一篇文章介紹了如何由 frame.xsl 定義的總框架和與具體視圖相關的主面板來構建所有視圖。在同組視圖的總面板中,可以包括一個與具體組相關的“內(nèi)層框架”樣式表,它產(chǎn)生組中所有視圖共同具有的那些響應。最后,內(nèi)層框架再調用與具體視圖相關的樣式表,就像在 frame.xsl 中調用主模板那樣。這種“層疊”機制如圖 1 所示。


          圖 1:子框架

          “層疊”機制能應用到任何一層,從而形成組嵌套。

          小結:強化應用結構
          本部分介紹了如何對應用提供的視圖進行分組,以便于開發(fā)和更改管理。我推薦了兩種實現(xiàn)分組的方法:

          • 允許在 XML 元數(shù)據(jù)中定義組 ― 例如,在導航信息中。
          • 使用 XSL 層疊樣式表。




          回頁首


          性能:緩存探討

          現(xiàn)在我們研究一下我們的 Web 應用的性能。有多種方法可用來提高類似 WebCal 樣例那樣的原始應用的性能,最強有力的方法之一便是緩存。

          生成 XML、然后再用 XSLT 將它轉換成客戶機首選格式的過程涉及許多步驟。根據(jù)對系統(tǒng)需求的不同,可以在幾個不同的起點引入緩存。基本而言,可以通過對轉換的中間結果進行緩存來提高性能,此處可以使用 URL 請求(就是 action 名和所有的 HTTP 參數(shù))、用戶名和預期格式的組合,并將該組合用作緩存的散列鍵。

          存在三種緩存方法,它們可以結合使用:

          • 緩存 XSL 樣式表
          • 緩存 XML
          • 緩存響應,表示 XML 已經(jīng)用 XSL 樣式表轉換成了用戶的首選格式。

          下面將對三種方法逐一深入探討。

          緩存 XSL 樣式表
          觀察第一篇文章中的 XSL 轉換代碼(清單 16),可以發(fā)現(xiàn)每次將對一個請求的 XML 響應(或者新產(chǎn)生的,或者從緩存中獲取的)轉換為客戶機的首選格式時,在實際轉換發(fā)生之前總要完成以下兩個步聚:

          • 創(chuàng)建 XSLProcessor 類的一個實例
          • 上面創(chuàng)建的處理器對轉換所需的樣式表進行分析。

          XSLProcessor 實例可以在樣式表分析完成后進行緩存,以備后用。由于處理器與請求者和參數(shù)無關,緩存散列鍵就可以僅由 HTTP 的 action 參數(shù)值組成。該參數(shù)決定了要顯示的視圖和客戶機的首選格式(例如 HTML)。這樣,當用戶請求某個視圖后,緩存的處理器實例就可用來處理其他用戶對此視圖的請求。

          此方案的好處在于避免了每次請求視圖時都要實例化一個 XSLProcessor 實例并進行樣式表分析。這就意味著一個緩存的處理器可以被所有用戶使用,效率很高。

          此方案可在 WebCal 的 WebCalUtilities.transform(...) 方法中實現(xiàn),如 清單 10 所示。它將樣式表 URI 作為散列鍵,其中包含 action 的名稱和格式(URI 的格式如下: http://localhost/webcal/<format>/<actioname>.xsl )。

          緩存 XML
          WebCal 已經(jīng)實現(xiàn)了一項簡單的性能優(yōu)化:navigation.xml 文件或用于其他格式的文件在 servlet 首次被加載并初始化時就同時被讀入。產(chǎn)生的導航 XML 文檔碎片先接格式緩存,然后在響應客戶機請求時添加到所生成的視圖 XML中。

          下一步是緩存在響應請求時創(chuàng)建的完整 XML 文檔。為此,您只需使用一個 hashtable 或者一個類似的集合來存儲 XML 文檔。這樣,每當用戶返回到他們已經(jīng)訪問過的頁面時,URL 請求總會或多或少有些相似之處 ― 至少相關的參數(shù)、用戶名、action 名稱、期望格式、視圖特定的參數(shù)將會是相同的。如果用這些參數(shù)計算散列鍵,則很容易在緩存中找到同一視圖的舊版本。該方法的好處在于不用頻繁地訪問后端應用(數(shù)據(jù)庫、EJB 等)。

          該方法可以在 WebCal 的 ShowAction.displayResult() 方法中實現(xiàn)。但我更喜歡下面的方法,盡管相似卻更有效。其代碼樣例參見清單 1113

          緩存響應
          這一方法是剛介紹的 XML 緩存和樣式表緩存的結合。緩存響應的優(yōu)勢是,如果之前曾有過同樣的請求并且結果仍存在緩存中,那么就可以在很短的時間內(nèi)直接從服務器上得到響應。它的工作機制與上面介紹的 XML 緩存方法很相似,只是在這里整個轉換過程的最后結果都被緩存,使用的散列鍵與上面的相同。此方法的優(yōu)點是訪問后端的頻率較低, 并且不必反復分析樣式表。

          此方法可以在 WebCal 的 ShowAction.displayResult() 方法中實現(xiàn),如清單 1113所示。

          為了讓 清單 11 正常運行,必須對 ShowAction.java 或其超類 Action.java 作一定的修改,如清單 12 所示:


          清單 12: 修改后的 Action 類 (在 Action.java 或 ShowAction.java 中)
          												
          														

          在 Action.java :
          protected static Hashtable cache = new Hashtable();
          ...
          // 字節(jié)數(shù)組的包裝(內(nèi)部類)
          protected class CachedResponse
          {
          public byte[] responseBytes;
          public CachedResponse(byte[] responseBytes)
          {
          this.responseBytes = responseBytes;
          }
          }


          最后,執(zhí)行 XSL 轉換的方法還應返回轉換的結果,以便將其保存在緩存中。我在此處選擇 byte[] (字節(jié)數(shù)組)作為數(shù)據(jù)類型是因為它獨立于任何具體的字符編碼。 清單 13 顯示了必要的修改。

          缺點:緩存清除和依賴性
          利用緩存提高性能有幾個缺點。每當一個用戶通過 Web 應用接口作了某些更改時,XML 緩存或響應緩存必須執(zhí)行相關性檢查。從緩存中刪除需要更新的頁面。

          處理此問題最簡單的辦法是為作出更改的用戶清除緩存。但是,如果系統(tǒng)允許用戶間交互 ― 例如,數(shù)據(jù)共享、小組日歷、會議邀請和調度變更 ― 則當僅有一個用戶更改某些數(shù)據(jù)時,所有用戶的緩存都要被清除。

          為了獲得更高的效率,緩存還應當保存每個頁面的相關性信息 ― 頁面所依賴的那部分系統(tǒng)。例如,WebCal 中的星期視圖依賴于用戶登錄的那一周所創(chuàng)建、修改和刪除的事件。相關性信息及其它附加信息,例如比較緩存數(shù)據(jù)日期與后端(數(shù)據(jù)庫)數(shù)據(jù)日期的時間戳,可以存儲于 清單 12 定義的 CachedResponse 類中。

          正面評價:不必清除 XSL 處理器緩存。與樣式表關聯(lián)的 XSL 處理器可以一直使用到樣式表改變?yōu)橹梗珮邮奖淼母囊话悴粫谶\行時發(fā)生。

          不僅僅是緩存
          緩存中的信息可用來分析用戶行為,例如登錄后通常進行什么操作。使用這些信息,可以預先生成頁面并以動態(tài)鏈接方式提供給用戶,也可只將預先生成的頁面保存于緩存中,當客戶機發(fā)出請求時即可快速訪問。

          性能:學有所獲
          本部分介紹了如何使用不同的緩存方法提高應用的性能:緩存 XSL 處理器實例,緩存 XML,以及緩存 XSL 轉換的實際結果。緩存的內(nèi)容可用于統(tǒng)計計算,這反過來又可用來預先生成用戶在會話期間可能會請求的頁面。





          回頁首


          小結

          在第一篇文章中,我介紹了使用 XML 和 XSL 轉換創(chuàng)建可擴展 Web 應用的基礎知識。本文接著介紹了如何添加一些高級功能。

          主要內(nèi)容是:

          • 使用國家語言支持實現(xiàn)多語言全球訪問
          • 強化應用結構,以方便維護、更改管理以及進一步的開發(fā)。
          • 緩存是如何提高性能的。

          要使 Web 應用更富有專業(yè)色彩并使它們能夠隨時在線運行,所有這些都是很重要的因素。





          回頁首


          參考資料

          下載 WebCal 應用樣例(Windows .zip 格式)。





          回頁首


          關于作者

          Martin Gerlach,在 IBM Almaden 研究中心計算機科學部從事畢業(yè)后研究工作 擁有德國漢堡應用科學大學的計算機科學學位。可以通過 mgerlac@almaden.ibm.com 與 Martin 聯(lián)系。


          posted on 2006-03-21 23:30 Vincent.Chen 閱讀(304) 評論(0)  編輯  收藏 所屬分類: XML

          主站蜘蛛池模板: 柞水县| 仁化县| 永德县| 庆元县| 珠海市| 新绛县| 广宁县| 特克斯县| 嘉义县| 临江市| 东台市| 潮州市| 林芝县| 宣武区| 天门市| 淅川县| 信丰县| 颍上县| 建始县| 福建省| 乌兰浩特市| 邢台县| 长治县| 平远县| 淮北市| 凤台县| 河源市| 郴州市| 巨鹿县| 班戈县| 新干县| 米脂县| 恩平市| 板桥市| 鹤壁市| 梁山县| 昌宁县| 保定市| 绍兴市| 康平县| 辽阳市|