国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用 JavaServer Pages 技術開發(fā)多語言 Web 應用程序
使用 JavaServer Pages 技術開發(fā)多語言 Web 應用程序
 

Norbert Lindenberg
2003 年 12 月

English: Developing Multilingual Web Applications Using JavaServer Pages Technology
日本語: JavaServer Pages 技術による多言語 Web アプリケーションの開発

JavaServer Pages (JSP) 技術現(xiàn)已成為深受 Web 應用程序開發(fā)者歡迎的工具。 使用 JSP 技術,開發(fā)者不需要其他的編程知識就可以設計出動態(tài)的 web 網(wǎng)頁。 同時,Web 開發(fā)者可以使用一種可擴展的標記機制來管理基礎軟件組件的功能。

通過 Java 標準制定組織(Java Community Process)開發(fā)的一個擴展功能可為多語言應用程序的開發(fā)提供更有力的支持。 JavaServer Pages 標準標記庫除了其他一些功能,還定義了一套可實現(xiàn)本地化和地區(qū)敏感(locale-sensitive)格式化的標記。

行文方面,本文首先對 JavaServer Pages 技術進行了簡要介紹,以使您能夠更好地理解如何使用它們解決國際化的問題。 然后,我會針對多語言 web 應用程序的開發(fā)討論幾個核心問題,并介紹如何使用 JavaServer Pages 技術解決它們:這些問題包括地區(qū)確定和本地化、字符編碼、格式化以及解析。

JavaServer Pages 技術

JavaServer Pages(和幾種相關技術)構成了 web 應用程序的表示層。 使用 JSP 技術,開發(fā)者可以創(chuàng)建動態(tài)的 web 頁面,這些頁面可以與商業(yè)邏輯(business logic)、數(shù)據(jù)庫以及其他可從網(wǎng)絡上獲取的服務形成互動關系。

JavaServer Pages

使用 JSP 技術開發(fā)的網(wǎng)頁結合了 HTML、XML 或其他含有類似 XML 標記(這些標記與基礎軟件庫連接)的靜態(tài)內(nèi)容,通常這些軟件庫使用 Java 編程語言編寫。 在這種環(huán)境中,非常重要的 Java 技術有 JavaBeans 組件架構(作為 JSP 和 Java 類之間的常規(guī)用途接口)、用于訪問 SQL 數(shù)據(jù)庫的 Java 數(shù)據(jù)庫連接(JDBC)API 以及各種用于 XML 處理的庫。

JSP 頁面本身按照 servlet 格式被編譯為 Java 代碼,以便執(zhí)行。 Servlet 是 web 服務器的擴展,它被編譯并關聯(lián)至服務器,從而可以獲得比腳本語言更快的執(zhí)行速度。 Servlet 直接以 Java 編程語言編寫,并經(jīng)常與 JSP 網(wǎng)頁一起使用,其中 servlet 作為控制部分而 JSP 頁面作為應用程序的視圖部分。

JavaServer Pages 和底層的 servlet 技術為處理 HTTP 請求和回應信息,以及使用 Cookies 或 URL 重寫進行會話維護都提供了廣泛的支持。

使用 JSP 技術的一個很重要的原因在于它可以將網(wǎng)頁作者和應用程序開發(fā)者的工作進行分離。 盡管可以將 Java 語句直接嵌入 JSP 網(wǎng)頁,但是,開發(fā)者們已經(jīng)認識到最好避免如此,而現(xiàn)在更傾向于使用自定義標記。

JavaServer Pages 標準標記庫

JavaServer Pages 標準標記庫(JSTL)包含了一系列涵蓋數(shù)個功能領域的自定義操作,這些功能在 JSP 網(wǎng)頁中經(jīng)常被使用。 該庫建立在許多參與者開發(fā)自己的庫時所獲得的經(jīng)驗基礎之上,它提供了一種應用程序可以依靠的標準接口,并且可以獨立于他們運行的服務器之外。

除了自定義標記,JSTL 還引入了一種表達語言,這種語言運進一步地減少了在 JSP 網(wǎng)頁中使用腳本語言的需求,同時還引進了標記庫驗證程序以限制在 JSP 網(wǎng)頁上對腳本和標記庫的使用。 這種改進版本的表達語言,以及限制腳本的功能已在隨后被集成到 JSP 2.0 規(guī)范之中,所以只有使用 JSP 1.2 時才要求 JSTL。

自定義操作包括的主要內(nèi)容是:

  • 變量操作: “核心”庫中的一些操作,可在不同的領域(網(wǎng)頁、請求、會話和應用程序)中定義、刪除變量或者將變量植入生成的頁面中。
  • 控制流: “核心”庫中的幾種操作,提供了基于標記的控制流結構(例如條件和迭代器),以減少對嵌入腳本語言代碼的需求。
  • URL 相關操作: “核心”庫中的一些操作,可讓 JSP 網(wǎng)頁導入由 URL 定義的內(nèi)容,可將內(nèi)部形式的 URL 重寫為外部形式(這可能包括收集會話跟蹤信息)或重新定向至一個不同的網(wǎng)頁。
  • XML 處理: “xml”庫中的操作,包括解析 XML 文檔并使用 XPath 表達式來解壓縮內(nèi)容,基于 XPath 表達式的控制流以及使用 XSLT 樣式表進行的轉換。
  • 關系數(shù)據(jù)庫訪問: “sql”庫中的操作,允許 web 應用程序執(zhí)行簡單的 SQL 查詢和更新。
  • 國際化和格式化(本文的中心內(nèi)容):“fmt”庫中的操作,支持地區(qū)確定、本地化、字符編碼決定和地區(qū)敏感格式化與解析。

地區(qū)確定和本地化

設計多語言 web 應用程序時,您必須首先決定如何確定用戶的語言和地區(qū)首選項,以及如何使這些首選項與該應用程序和基礎的 Java 運行環(huán)境支持的一套地區(qū)設置相匹配。 這部分首先描述了 web 應用程序必須具有的外部環(huán)境和要求。 下一步,我們將了解相關的 Java 2 Standard Edition (J2SE) 平臺提供的功能,最后我們將了解 JavaServer Pages 標準標記庫的標記如何連接到環(huán)境和 J2SE 中。

確定用戶首選項

web 應用程序有兩種方法來確定用戶的語言首選項:首先,它可以由瀏覽器使用 HTTP 請求報頭字段 Accept-Language 傳輸至服務器的語言和地區(qū)首選項。 盡管標準規(guī)定了許多語言標記,但是一般使用 ISO 639 語言代碼(如 ja 為日文)和 ISO 3166 國家代碼(如 IT 代表意大利)。 瀏覽器通常讓用戶創(chuàng)建一個語言列表作為其首選項的一部分。 然而,這種方法不太可靠;用戶不一定會創(chuàng)建該列表,而且該列表不一定會包含該應用程序支持的地區(qū)設置。 由于這些不確定性,多語言應用程序通常采用第二種方法:他們讓用戶直接從支持語言的列表中選擇,并把選擇的語言作為用戶資料的一部分進行保存,或只在進行該會話的時候保存。 一個好的方法是,在對用戶一無所知的情況下,首先使用 Accept-Language 信息,在應用程序的開始頁面中給予用戶直接選擇語言的機會。

Accept-Language 地區(qū)設置主要用于語言和文化首選項是沒什么意義的。 例如,它們不應該被解釋為表示用戶居住的國家。 同樣,在很多情況下瀏覽器提供的地區(qū)設置只有一個語言代碼,而一些地區(qū)敏感的功能(例如,日期格式)則隨著國家的不同而相異。 在很多情況下,通過語言假設主要國家的規(guī)范是合理的(如果沒有指定國家);例如,如果指定了日本語,則可使用日本通用的日期格式。 然而,如果是根據(jù)國家而設置的重要功能(例如貨幣),則必須給用戶一個機會來修正該假設。

在許多情況下,web 應用程序是由若干組件組合而來的,這些組件可能已經(jīng)本地化為不同的語言。 一個特別值得一提的組件是 Java 運行環(huán)境,它在一些地區(qū)敏感區(qū)域可能具備支持超過 40 種語言中的 100 種區(qū)域設置的功能(例如日期格式),遠遠超出了典型的 web 應用程序。 因此,應用程序開發(fā)者必須決定是否在整個應用程序中限制所支持語言的本地化功能,或者充分發(fā)揮每個組件的功能優(yōu)勢。 第一種方法的優(yōu)勢在于用戶可以看到的全部頁面都使用同一語言,而第二種方法可能導致頁面中存在不同的語言——其中一種語言出現(xiàn)在絕大多數(shù)文本中,而另一種則出現(xiàn)在例如日期的格式中。

Java 2 Standard Edition Platform 中的本地化

為了了解 JSTL 如何確定應用程序被哪些地區(qū)設置支持,我們來看看在基礎的 Java 2 Standard Edition 平臺中是如何進行本地化的。 java.util 軟件包的核心主要有兩種類:LocaleResourceBundle。

Locale 對象只是用來確定地區(qū)設置的:它們結合了 ISO 639 語言代碼(例如,ja 代表日文)和 ISO 3166 國家代碼(例如,IT 代表意大利),還可能包含一個(非標準化的)變量字符串。 注意,HTTP 的地區(qū)標識符使用相同的 ISO 標準,所以對比通常比較容易。

ResourceBundle 對象是本地化對象的容器,形成成鍵/值對。 一個基礎資源束定義了一個基礎束的名稱、一套鍵以及默認值(通常是英文值,但不是必須的)。 例如,一個簡單的 Messages 資源束可能定義 greeting-day 鍵的默認值為 Hello。 其他的特定語言和國家束可以被定義,其名稱由基礎名稱組成(通過后綴指示其語言、國家和變量)并提供已本地化的值。 例如,德語 Messages_de 資源束可以給出 Guten Tag 值(針對 greeting-day 鍵),而一個奧地利 Messages_de_AT 束可能用 Servus 值來覆蓋該值。 資源束可以作為 Java 類或簡單的“屬性”文本文件來執(zhí)行。

JavaServer Pages 應用程序的本地化方法

要對基于 JavaServer Pages 技術的應用程序進行本地化,方法通常有兩個。 第一個方法是使用國際化的頁面,這些頁面??梢酝ㄟ^自定義標記從資源束獲得與特定地區(qū)設置相關的內(nèi)容。 如果頁面需要保持復雜的結構并與所有地區(qū)設置同步,則通常會采取這種方法。 第二種方法使用單獨的特定地區(qū)設置頁面以及分發(fā)到適當頁面的 servlet(取決于用戶的地區(qū)選擇)。 如果頁面包含的主要是文本或者地區(qū)設置間的結構截然不同時,則通常會采取這種方法。

地區(qū)確定和 JSTL 中的本地化

JSTL 構建于 J2SE 工具之上,它可進行地區(qū)確定和本地化。 使用任何一種 JSP 本地化方法(如上所述)均可以進行地區(qū)確定,而本地化功能的目的是為國際化的頁面提供支持。

JSTL 對上述兩種確定用戶地區(qū)首選項的方法都提供支持。 應用程序可以使用 JSTL 的 <fmt:setLocale> 操作,指定一個固定的地區(qū)(通常是用戶從支持語言列表中所直接選擇的)。 一旦使用了該操作,指定的地區(qū)設置將應用于所有的地區(qū)敏感操作中。 如果沒有使用 <fmt:setLocale> 操作,地區(qū)敏感操作將會從地區(qū)選擇列表中搜索第一種支持的地區(qū)設置,這些地區(qū)設置通常由 Accept-Language 報頭提供。

下面是一些您可以用于 web 應用程序開始頁面的代碼片斷。 這些代碼片斷可讓用戶非常輕松地選擇他或她的地區(qū)設置。 假設這些代碼是 locale-choice.jsp 頁面中的一部分:

<%-- Interpret user‘s locale choice --%>            <c:if test="${param[‘locale‘] != null}">            <fmt:setLocale value="${param[‘locale‘]}" scope="session" />            </c:if>                         <%-- Offer locale choice to user --%>            <a href="locale-choice.jsp?locale=en-US">USA</a> -            <a href="locale-choice.jsp?locale=de-DE">Deutschland</a> -            <a href="locale-choice.jsp?locale=ja-JP">日本</a>                         <%-- Use URL rewriting to ensure proper session tracking --%>            <form method="get" action="<c:url value=‘/locale-choice.jsp‘ />">            <input type=submit value="Stay in session">            </form>

第一部份(此部分必須在生成的 HTML 頁面任何內(nèi)容之前)表示用戶的地區(qū)選擇,該選擇作為一個請求參數(shù)顯示在 JSP 頁面上。 如果定義了 locale 參數(shù),則它將被用于進行會話的地區(qū)設置。

第二部分(此部分是生成的 HTML 頁面內(nèi)容的一部分)為用戶提供了返回同一頁面的鏈接,但是根據(jù)選定的國家提供了 locale 參數(shù)設置。 注意,在本地語言中已經(jīng)給出國家的名稱,所以即使頁面的其他部分已經(jīng)本地化為用戶不能識別的語言,但是用戶仍然可以容易地識別這些名稱。 例如,“日本”是“日本”的數(shù)字字符引用,即“日本”的日語單詞。 新版的瀏覽器如果裝有日本字體,將會正確地轉換這些文本;對于舊版的瀏覽器,使用圖片則可能更合適一些。

最后一部分顯示如何使用 <c:url> 標記生成 URL,此 URL 包含了一個會話 ID,如果需要對該會話進行追蹤的話(如果用戶啟用了 cookies,則 cookies 將代替 URL 重寫)。 這將確保一旦選擇了地區(qū)設置,該選擇將應用于該 web 應用程序中的所有頁面。

如果從 web 應用程序本身的用戶界面中選擇了地區(qū)設置,然后使用 <fmt:setLocale> 進行設置,那么就可以假設該應用程序確實支持此地區(qū)設置。 另一方面,如果沒有使用 <fmt:setLocale> 并且 JSTL 必須從 Accept-Language 報頭中的地區(qū)設置列表中找到一個支持的地區(qū)設置,那么情況會變得更復雜。

要決定哪個地區(qū)設置是被支持的,JSTL 將參考該應用程序所使用的資源束。 有兩種操作可用于訪問資源束:<fmt:bundle><fmt:setBundle>。 它們的基本功能是相同的:它們查詢一個資源束并創(chuàng)建一個“本地化環(huán)境”,在這個“本地化環(huán)境”中包含了對該資源束和用于請求該資源束的地區(qū)設置的引用。

<fmt:bundle><fmt:setBundle> 操作所使用的資源束查詢允許多次請求地區(qū)設置(這樣它就可以處理由 Accept-Language 報頭提供的列表),并使用由 web 應用程序定義的備用(fallback)地區(qū)設置。 如果使用 <fmt:setLocale> 操作設置地區(qū),那么 <fmt:bundle><fmt:setBundle> 操作將請求用于該地區(qū)設置的束,或者,如果不成功的話,將請求用于備用地區(qū)設置的束。 如果沒有使用 <fmt:setLocale>,隨后的操作將請求用于由 Accept-Language 報頭提供的地區(qū)設置和備用地區(qū)設置,直到請求成功。 在每種情況下,基本查詢(查詢束的基本名稱和一個請求地區(qū)設置)將為請求地區(qū)設置本身搜索一個資源束,隨后搜索更簡單的地區(qū)設置(首先從請求地區(qū)設置中舍棄變量,然后舍棄國家組件)。 如果全部的請求地區(qū)設置以及備用地區(qū)設置的查詢都失敗,那么將使用基礎束。

以下是一些例子。 讓我們假設某個應用程序擁有用于 en、zh_CNzh_TW、jako 的束。 備用地區(qū)設置被設置為 en。 沒有使用 <fmt:setLocale> 標記。 下表顯示最終本地化環(huán)境的束和地區(qū)設置(用于一些請求地區(qū)設置列表):

被請求的地區(qū)設置

結果束

結果地區(qū)設置

zh_SG、zh_CN

zh_CN

zh_CN

zh、ja

ja

ja

es_MX

en

en

en_US

en

en_US

ja、zh_CN

ja

ja

ResourceBundle 類的行家會注意到,JSTL 操作所使用的查詢策略與 ResourceBundle 所使用的查詢策略是不同的。 ResourceBundle 使用的策略只接受一個請求地區(qū)設置,這不足以處理由 Accept-Language 報頭所提供的地區(qū)設置列表,并且它會恢復 Java 運行環(huán)境的默認地區(qū)設置,此默認地區(qū)設置與 web 應用程序和其用戶并不相關,使用它將導致不可移植性。

那么,為什么查詢資源束時存在兩種不同的操作呢? 它們的區(qū)別在于它們使用的方法:<fmt:bundle> 標記提供了一個用于嵌套標記的環(huán)境,而 <fmt:setBundle> 操作將最終本地化環(huán)境存儲在一個變量中,此變量可以在相同頁面中被后繼操作訪問,并且可以被其他頁面中的操作所訪問(這取決于該變量的范圍)。

<fmt:message> 操作是一種利用本地化環(huán)境的 JSTL 標記。 它最簡單的形式是,它從一個本地化環(huán)境的資源束中為一個指定的鍵獲取一條信息并將該信息插入生成的頁面中。 下面例子顯示了它的不同用法:

<fmt:setBundle basename="Errors" var="errorBundle" />            <fmt:bundle basename="Messages">            <%-- Localization context established by <fmt:bundle> tag --%>            <fmt:message key="greeting" />            <p>            <%-- Localization context established by <fmt:setBundle> tag --%>            <fmt:message key="emptyField" bundle="${errorBundle}" />            </fmt:bundle>

其次,為什么有一個請求地區(qū)設置與本地化環(huán)境相關聯(lián)? 這個地區(qū)設置是 JSTL 將格式化標記限制到應用程序所支持的語言范圍內(nèi)的方法,這樣展現(xiàn)在讀者面前的頁面語言將完全統(tǒng)一。 嵌套于 <fmt:bundle> 標記中的格式化操作使用該標記的本地化環(huán)境來確定它們應該使用的地區(qū)設置。 例如,讓我們觀察下面的頁面片斷:

<jsp:useBean id="now" class="java.util.Date" />            <fmt:formatDate value="${now}" timeStyle="long" dateStyle="long" />            <p>            <fmt:bundle basename="Messages">            <fmt:formatDate value="${now}" timeStyle="long" dateStyle="long" />            </fmt:bundle>

如果 HTTP Accept-Language 地區(qū)設置是 fren,并且基礎的 Java 運行環(huán)境對這兩種語言的日期格式都支持(但 web 應用程序的 Messages 束只存在于 en),那么第一個日期采用法文格式,而第二個則采用英文格式。 因此,頁面設計者可以決定是使用統(tǒng)一的語言還是通過選擇適當?shù)臉擞浨短讈砝盟鞋F(xiàn)有的本地化信息。

最后,為什么本地化環(huán)境使用請求地區(qū)設置而不使用由資源束找到的地區(qū)設置? 答案是,這樣可以避免丟失重要的信息,某些格式標記可能需要這些信息。 很多應用程序不能區(qū)分相同語言中不同變量之間的區(qū)別,而且只提供(例如)英文資源束,期望著這些文本在英國、澳大利亞和新加坡都能被同樣理解。 然而對于日期格式,國家是很關鍵的——對于英國讀者來說,“2/6/02”表示“ 2002 年 6 月 2 日”,但對于習慣美國規(guī)范的讀者來說,則表示“2002 年 2 月 6 日”。 所以,在很多情況下,如果使用了請求地區(qū)設置(而不是資源束地區(qū)設置),則國家信息將會被保留。

字符編碼

當前,我們使用兩種截然不同的模塊表示存儲在計算機中或通過網(wǎng)絡傳輸?shù)奈谋荆号f的字符編碼模式專門用于較小的語言集合、國家和/或操作系統(tǒng)(包括如 ISO 8859 系列、 Windows 代碼頁和 EUC 編碼);而新的基于 Unicode 編碼的模式能夠(至少理論上能夠)表示所有的語言并可以在任何地方使用。

舊的模塊具有很大的劣勢:

  • 每種舊的字符編碼方法通常只支持一個小的語言集合。 例如,Shift-JIS 支持日文和英文,但不支持其他的亞洲或歐洲語言。 ISO 8859-1 支持一些西歐語言但不支持東歐語言。
  • 字符轉換可能會帶來意料之外的信息丟失。 開發(fā)者通常選擇 ISO 8859-1 作為德語、法語和其它西歐語言的編碼方法,然后會很驚訝地發(fā)現(xiàn)“€”字符(德國、法國和許多其他歐洲國家通用貨幣的標志)不被這種編碼所支持。 為了防止這種信息丟失,您必須使用 Windows-1252、ISO 8859-15 或其他編碼方法,這取決于瀏覽器的基礎操作系統(tǒng)。

當前版本的主要軟件系統(tǒng)所包含的創(chuàng)建、分發(fā)和解釋 web 內(nèi)容都支持新的模塊;它們通常將 Unicode 用于內(nèi)部處理,或者至少知道怎么使用(用于 web、基于 Unicode 編碼的)UTF-8。 基于 Unicode 的編碼有著以下顯著的優(yōu)勢:它們支持多語言頁面并清晰區(qū)分地區(qū)設置(從字符編碼處理)問題。 同樣,因為編碼轉換而帶來的信息丟失的風險也很小,同時基于 Unicode 的編碼與現(xiàn)在的服務器和客戶端系統(tǒng)比較吻合。

盡管如此,很多 web 開發(fā)者仍然不太愿意使用 UTF-8。其中的原因可能包括對舊版本的瀏覽器支持不充分,或者缺少支持它的工具。

JavaServer Pages 技術對新舊兩種模塊都支持。 現(xiàn)在我們來看看字符編碼問題所涉及的各種不同領域,并了解 JSP 技術和 JSTL 如何處理它們。

處理源程序頁編碼

JSP 源文件的編碼通常由可用的編輯工具決定,所以可能使用特定國家和操作系統(tǒng)的編碼。 字符編碼與 JSP 運行環(huán)境(“容器”)之間的通訊方法有許多種,隨著時間推移其中的機制和規(guī)則已不斷改進。 同時 JSP 源文件相應存在著兩種語法:標準語法和基于 XML 的新語法。

在檢測字符編碼時,JSP 2.0 規(guī)范將在這兩種語法中進行辨別。 對于采用 XML 語法的文件,編碼將被檢測為采用 XML 規(guī)范;這意味著 UTF-8 或 UTF-16 為默認的編碼,而其他的編碼必須在文件開始處的 XML 聲明中予以說明。 對于采用標準語法的文件,容器將考慮兩種主要的信息來源:首先它們訪問應用程序的配置描述符,查詢一個 page-encoding 元素,該元素位于 jsp-property-group(其 URL 格式與文件相匹配);然后在此頁中查詢 pageEncoding 屬性。 如果兩者都沒有,容器也會尋找 contentType 屬性中的 charset (參閱下一部分“處理 Web 頁面編碼”),或使用 ISO 8859-1 作為最終的備用選擇。

以下是基于 JSP 2.0 的應用程序的一些簡單建議:對于采用 XML 語法的文件,確保沒有使用 UTF-8 或 UTF-16 編碼的文件能夠正確識別它們的字符編碼。 對于采用標準語法的文件,如果您對所有源文件使用 UTF-8,則請在配置描述符中只使用一個元素 page-encoding 來闡述它。 如果您使用特定地區(qū)設置編碼,則根據(jù)該地區(qū)設置來組織或命名您的文件,并使用 page-encoding 元素來描述它們的關系。 例如,如果全部的韓文文件以 EUC-KR 編碼并保存在 /ko/KR web 的應用程序的子目錄中,請使用以下語句:

<jsp-property-group>            <url-pattern>/ko/KR/*</url-pattern>            <page-encoding>EUC-KR</page-encoding>            </jsp-property-group>

如果應用程序中的源文件不能以這種方式組織,則為每個源文件添加 pageEncoding 屬性。 不過請切記,此屬性必須能夠在文件的開始處找到并且只能用于標識 ASCII 擴展碼的字符編碼。 后一個限制考慮到了 UTF-8 和許多舊的字符編碼,但沒考慮 UTF-16 或基于 EBCDIC 的編碼。 不建議根據(jù) contentType 屬性中的 charset 值來標識源程序頁編碼;這個值應只用于標識 web 頁面編碼(參見下一部分)。

關于源文件字符編碼,JSP 1.2 規(guī)范沒有清楚地區(qū)分使用標準語法的文件和使用 XML 語法的文件。 它也沒有提供識別配置描述符中的字符編碼的方法。 為確保正確檢測字符編碼,設計用于 JSP 1.2 容器的應用程序應總是識別每個使用 pageEncoding 屬性的源文件中的字符編碼。

JSTL 定義了一個<c:import> 操作,該操作允許包含由 URL 指定到 JSP 生成的頁面的外部數(shù)據(jù)。 該操作允許字符編碼規(guī)范,如果外部數(shù)據(jù)沒有指定它本身的編碼時會使用此規(guī)范。

處理 Web 頁面編碼

web 應用程序必須選擇生成的 web 頁中使用的字符編碼(該編碼被稱為“反應字符編碼”),它基于目標瀏覽器的性能、頁面內(nèi)容的編寫系統(tǒng)和語言以及可能的瀏覽器主機的操作系統(tǒng)。 根據(jù) HTTP 規(guī)范,字符編碼在 Content-Type 實體報頭的 charset 參數(shù)中被指定。

如果所有目標瀏覽器都支持 UTF-8,一般來說最好使用這種編碼,這樣就可以支持多語言文檔并避免字符轉換帶來的信息丟失。

如果不能使用 UTF-8 ,必須小心謹慎地使用應用程序將字符編碼與使用的語言相匹配,包括一些特殊字符。 為防止出現(xiàn)錯誤,可能需要在整個頁面里使用同一種語言,如本文開始部分“地區(qū)確定和本地化”中所述。 同樣,也有必要避免使用“€”字符。

Web 應用程序可以直接指定一個頁面的字符編碼,也可以讓 JSP 技術根據(jù)地區(qū)設置信息間接決定。

  • 通過頁面的 contentType 屬性的顯式規(guī)范最為簡便,該屬性可讓應用程序連同生成頁面的內(nèi)容類型一起來指定字符編碼。 如果應用程序在處理請求時需要設置字符編碼,則它需要使用一個自定義操作或一些 Java 代碼來調(diào)用 javax.servlet.ServletResponse.setContentType 方法或新的(在 Servlet 2.4 中)javax.servlet.ServletResponse.setCharacterEncoding 方法。
  • 間接地,每當字符編碼創(chuàng)建一個本地化環(huán)境時,它們也是由 JSTL 格式化操作(包括 <fmt:message>)以及 <fmt:bundle>、<fmt:setBundle><fmt:setLocale> 操作無條件地來決定。 通過 ServletResponse.setLocale 方法,它們將本地化環(huán)境的地區(qū)設置或指定的地區(qū)設置映射到一個字符編碼并根據(jù)頁面的內(nèi)容類型對其進行設置。 Servlet 2.4 規(guī)范通過配置描述符中的 locale-encoding-mapping-list 元素為應用程序提供了一個控制映射的方法。 如果應用程序沒有提供此元素,或者當您使用基于舊的 Servlet 規(guī)范的容器時,那么從地區(qū)設置到字符編碼的映射取決于該容器;典型的實現(xiàn)依賴于舊的字符編碼。

間接決定字符編碼是可行的,只要舊的字符編碼可以被接受,并且整個頁面使用相同的語言而且避免出現(xiàn)常用字符編碼所不支持的特殊字符。 然而,若要利用 UTF-8 則要求使用顯式規(guī)范。 因為 Servlet 2.4 規(guī)范使顯式規(guī)范優(yōu)先于隱式規(guī)范,所以將字符編碼設置為 contentType 屬性的一部分已足夠——隨后使用 JSTL 格式化操作不會影響字符的編碼。 不過,在早期版本的 Servlet 規(guī)范中,并不保證地區(qū)設置信息中的顯式規(guī)范優(yōu)先于隱式?jīng)Q定。 如果需要與基于舊規(guī)范的容器兼容,您必須通過在顯式字符編碼規(guī)范和首次使用自定義操作之間調(diào)用 ServletResponse.flushBuffer 來凍結字符編碼,這些自定義操作可能間接決定字符編碼。

處理請求參數(shù)編碼

JSP 技術不僅能夠生成 web 頁面,而且還可以接收和解釋與 HTTP 請求一起收到的參數(shù)——通常是來自某種表格的輸入,這種表格屬于前面生成的 web 頁面的一部分。 用于這些參數(shù)的字符編碼并非在任何地方都被指定,但實際標準是瀏覽器使用的編碼要與包含這些表格的網(wǎng)頁使用的編碼相同。

這意味著 web 應用程序需要跟蹤先前生成的網(wǎng)頁的編碼。 一個常用的機制是把編碼的名稱存儲到表格本身的一個隱藏域中,在下一個請求時解壓縮為第一個參數(shù),然后用它來解碼出其他的參數(shù)。 然而,JSP 頁面還可以使用會話管理來跟蹤請求之間的信息。

應用程序可以使用 JSTL 自定義操作 <fmt:requestEncoding> 來指定要編碼的參數(shù)的編碼方法。 如果應用程序總是發(fā)送 UTF-8 編碼的頁面,那么可以簡單指定這種編碼為請求編碼。 否則,如果它將直接指定生成頁面的編碼,它應該將該編碼作為會話信息的一部分進行跟蹤并直接將其傳遞給 <fmt:requestEncoding> 操作。 如果它依賴于字符編碼的間接決定,則它會簡單地使用 <fmt:requestEncoding> 操作而無需指定一種字符編碼;間接決定生成頁面的編碼這一操作還會在會話中儲存信息,<fmt:requestEncoding> 可以檢索和使用這些信息。

格式化和解析

以本地化的格式表示數(shù)據(jù)(如數(shù)字和日期)是任何類型地應用程序都要完成的常見任務,就如同用戶提供的輸入解釋。 不同語言和文化所使用的格式區(qū)別很大,所以如果開發(fā)者不依靠現(xiàn)有的庫的話,那么這個工作就不會是一項簡單的任務。

幸運的是,確實存在這樣的庫。 Java 2 Standard Edition (J2SE) 平臺提供了在 java.text 軟件包中用于格式化和解析常用數(shù)據(jù)類型的類庫,并且 Sun 已將這些類庫本地化為 100 多種地區(qū)設置。

JavaServer Pages 標準標記庫提供了自定義操作,可將這些功能直接應用到 JSP 頁面中。

用于格式化和解析操作的地區(qū)確定

您可以在預定義的本地化環(huán)境中對數(shù)字和日期使用格式化和解析的操作(例如,如果標記嵌套于一個 <fmt:bundle> 標記中),或者在這種環(huán)境以外進行操作。 如果您在預定義的本地化環(huán)境中使用操作,則它們將使用此本地化環(huán)境的地區(qū)設置。 否則,它們將決定 <fmt:bundle><fmt:setBundle> 操作(如前文所述)的,用于修改的資源束查詢策略所使用的地區(qū)設置。 主要的區(qū)別在于:與查找資源束不同,算法通過使用 java.text.NumberFormat.getAvailableLocales 方法(用于數(shù)字格式化和解析操作)或者 java.text.DateFormat.getAvailableLocales 方法(用于日期和時間格式化和分解操作)來決定受支持的地區(qū)設置。

數(shù)字格式化和解析

JSTL 用于數(shù)字格式化和解析的自定義操作 <fmt:formatNumber><fmt:parseNumber> 基于 J2SE 類 java.text.NumberFormat,用于處理簡單的數(shù)字以及百分比和貨幣值。

特別值得一提的是它們對貨幣格式化的支持。 傳統(tǒng)上,許多格式化庫假設貨幣符號可以從地區(qū)設置中得出——例如,如果地區(qū)設置是中國,那么貨幣符號就是人民幣(RMB)。 在一個跨境交易的環(huán)境中,這并沒有多大的意義。 如果某個英國公司以英鎊來計算價格,而 web 應用程序將價格顯示為人民幣(RMB)的形式,就會出現(xiàn)兩個問題:第一,人民幣的匯率比英鎊低;其次,人民幣換回英鎊會比較困難。 由于貨幣的選擇屬于商業(yè)上的決定,所以貨幣必須作為值的一部分而不是格式的一部分。

因此,<fmt:formatNumber> 操作可以讓應用程序指定一個 ISO 4217 貨幣代碼或貨幣符號,它將覆蓋本地化數(shù)字格式使用的默認貨幣。 假設應用程序使用一個帶有值和貨幣屬性的價格 bean,下面的頁面語句片斷可以對價格進行格式化:

<fmt:formatNumber type="currency" value="${price.value}"            currencyCode="${price.currency}" />

如果 JSP 頁面指定了一個貨幣代碼,則底層的 NumberFormat 對象會嘗試對指定的貨幣使用一個貨幣符號,該指定的貨幣已本地化為所處本地化環(huán)境的地區(qū)設置。 例如,如果為美元指定貨幣代碼 USD,則它可能會使用符號“$”(如果地區(qū)設置是en_US),在其他可接受該貨幣符號的地區(qū)設置中將使用 US$,或者如果本地化符號未知,則使用備用貨幣代碼 USD。

日期和時間的格式化和解析

用于日期和時間的格式化和解析的 JSTL 自定義操作 <fmt:formatDate><fmt:parseDate> 基于 J2SE 類 java.text.DateFormat 并用于處理不同的日期和時間表示方法。

令人感興趣的一點是顯示的日期和時間不僅僅取決于一種指定地區(qū)設置的格式,還取決于時區(qū)信息。 用戶通常對服務器時區(qū)不感興趣,但另一方面,要找出用戶所在地的時區(qū)卻并不簡單。應用程序可以通過使用一些客戶端的 JavaScript 代碼來找出用戶的當前時區(qū)與格林尼治標準時間的偏差,或讓用戶指定當前時區(qū)并將其作為用戶信息的一部分。 JSTL 操作并沒有解決這個問題,但它們提供了兩個自定義操作,可以用來告知有關時區(qū)的日期和時間的格式化和解析:<fmt:timeZone><fmt:setTimeZone>。 與 <fmt:bundle><fmt:setBundle> 一樣,<fmt:timeZone> 標記可為嵌套標記定義時區(qū),而 <fmt:setTimeZone> 將時區(qū)儲存在一個變量中以供后繼操作使用。

信息格式化

<fmt:message> 操作(前面已提及)不但能從一個資源束中獲取一個字符串并將其插入至生成的頁面中,而且它還可以執(zhí)行參數(shù)替換并根據(jù)需要格式化參數(shù)。 它基于 java.text.MessageFormat 類,因此該操作獲取的字符串實際上是一個 MessageFormat 模式字符串。 <fmt:param> 操作提供了必要的自變量。

例如,如果 JSP 頁面包含了以下語句:

<jsp:useBean id="now" class="java.util.Date" />            <fmt:bundle basename="Messages">            <fmt:message key="greeting">            <fmt:param value="${now}" />            </fmt:message>            </fmt:bundle>

并且找到的資源束是德語,而且 為 greeting 鍵提供了“Willkommen! Heute ist der {0,date,long}.”值,那么生成日期為(假設)2002 年 6 月 21 日的頁面內(nèi)容將會是“Willkommen! Heute ist der 21. Juni 2002.”

結論

如本文所述,JavaServer Pages 技術(特別是 JavaServer Pages 標準標記庫)為您提供了一個開發(fā)多語言應用程序的堅實基礎。 您需要仔細考慮以下幾個設計選擇:如何確定用戶的語言和地區(qū)設置首選項,如何構造您用于本地化的 JSP 頁面,是否采用單一語言的頁面或充分利用現(xiàn)有的地區(qū)設置支持,以及使用哪一種字符編碼模塊。 JSP 技術使您能夠選擇其中任意一種,這樣您就可以將頁面以最佳的方式展示給全世界的讀者,而且最重要的是,以他們自己的語言來展示。

參考書目

R. Fielding et al.: Hypertext Transfer Protocol -- HTTP/1.1. RFC 2616. The Internet Society, 1999.

Dave Raggett et al. (ed.): HTML 4.01 Specification. World Wide Web Consortium, 1999.

Tim Bray et al. (ed.): Extensible Markup Language (XML) 1.0 (Second Edition). World Wide Web Consortium, 2000.

Java 2 Platform, Standard Edition, v 1.4.2 API Specification.Sun Microsystems, 2002.

Danny Coward (ed.): Java Servlet Specification. Version 2.3.Sun Microsystems, 2001.

Danny Coward, Yutaka Yoshida (ed.): Java Servlet Specification. Version 2.4.Sun Microsystems, 2003.

Eduardo Pelegrlopart (ed.): JavaServer Pages Specification. Version 1.2.Sun Microsystems, 2001.

Mark Roth, Eduardo Pelegr lopart (ed.): JavaServer Pages Specification. Version 2.0.Sun Microsystems, 2003.

Pierre Delisle (ed.): JavaServer Pages Standard Tag Library. Version 1.0.Sun Microsystems, 2002.

Pierre Delisle (ed.): JavaServer Pages Standard Tag Library. Version 1.1.Sun Microsystems, 2003.

關于作者

Norbert Lindenberg 是 Sun Microsystems 的 Java Web Services 團隊內(nèi) Java Internationalization 技術主管。在加盟 Sun 之前,曾經(jīng)供職于 General Magic 和 Apple Computer,參與過多個國際化項目。他畢業(yè)于德國的卡爾斯魯厄大學,擁有計算機科學理科碩士學位。

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
MyEclipse下開發(fā)JSF(1)
JavaServer Faces技術常見問題
developerWorks 中國:JavaServer Pages / Servlets
中文化和國際化問題權威解析之三:Java中文問題分析
JSP中文亂碼問題解決方法詳解
struts,ajax亂碼解決方案
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服