一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

JSTL 入門: 表示就是一切

 Long_way 2007-07-31
JSP 標(biāo)準(zhǔn)標(biāo)記庫(JSP Standard Tag Library,JSTL)fmt 庫通過一組頗受關(guān)注的定制標(biāo)記提供了用于訪問所有 Java 編程語言國際化功能的便利方式。Mark Kolb 研究了用于對數(shù)據(jù)進行格式化和國際化的 fmt 標(biāo)記。

在本系列的前幾篇文章中,我們討論了 JSTL 及其表達式語言(EL)。我們還研究了由 core 庫定義的定制標(biāo)記。具體而言,在“ JSTL 入門:表達式語言”中我們指出 EL 提供了一種簡化語言,用于在 JSP 應(yīng)用程序中訪問和操作數(shù)據(jù)并使該數(shù)據(jù)可被 JSTL 定制標(biāo)記用作動態(tài)屬性值。 core 庫包含了一些定制標(biāo)記,用于管理限定了作用域的變量、顯示 EL 值、實現(xiàn)迭代內(nèi)容和條件內(nèi)容以及與 URL 進行交互,這是“ JSTL 入門:探討 core”的主題。

我們接下來將討論的 JSTL 庫是 fmt 庫。 fmt 庫中的定制標(biāo)記支持通過資源束對文本內(nèi)容進行本地化,并支持對數(shù)字和日期的顯示和解析。這些標(biāo)記利用在 java.utiljava.text 包中實現(xiàn)的 Java 語言的國際化 API,因此如果您已經(jīng)很熟悉諸如 ResourceBundle 、 Locale 、 MessageFormatDateFormat 這樣的類,那么您將發(fā)現(xiàn) fmt 庫中有很多方面值得稱道。如果您不熟悉這些類,那么 fmt 庫的標(biāo)記用直觀的方式來封裝國際化 API,這種方式使您能夠很容易將本地化功能合并到 JSP 應(yīng)用程序中。

本地化

在 Java 語言國際化 API 中,影響數(shù)據(jù)本地化方式的因素主要有兩個。一個是用戶的 語言環(huán)境,另一個是用戶的 時區(qū)。語言環(huán)境表示某一特定區(qū)域或文化的語言習(xí)慣,包括日期、數(shù)字和貨幣金額的格式。一個語言環(huán)境始終會有一種相關(guān)聯(lián)的語言,在許多情況下這種語言是由多個語言環(huán)境共享的某種語言的方言。例如,美國英語、英國英語、澳大利亞英語和加拿大英語都具有不同的英語語言環(huán)境,而法國、比利時、瑞士和加拿大所用的法語方言則都具有不同的法語語言環(huán)境。


時區(qū)是數(shù)據(jù)本地化中的第二個因素,這僅僅是因為一些語言環(huán)境分布的地理區(qū)域很廣。當(dāng)您顯示有關(guān)跨洲語言環(huán)境(比如澳大利亞英語)的時間信息時,針對用戶時區(qū)定制數(shù)據(jù)與對其進行正確格式化一樣重要。

但是這就有了一個問題:應(yīng)用程序如何確定用戶的語言環(huán)境和時區(qū)?在 Java 應(yīng)用程序的情況下,JVM 能夠通過與本地操作系統(tǒng)進行交互來設(shè)置缺省語言環(huán)境和時區(qū)。雖然這種方法對于桌面應(yīng)用程序而言可以正常工作,但是它實際上并不適合于服務(wù)器端的 Java 應(yīng)用程序,因為這種應(yīng)用程序所處理的請求,可能來自于距離該應(yīng)用程序所駐留的服務(wù)器萬里之遙的地方。

幸運的是,HTTP 協(xié)議通過 Accept-Language 請求頭將本地化信息從瀏覽器傳遞至服務(wù)器。許多 Web 瀏覽器允許用戶定制他們的語言首選項,如圖 1 所示。通常,那些沒有為一種或多種首選語言環(huán)境提供顯式設(shè)置的瀏覽器會詢問操作系統(tǒng)以確定在 Accept-Language 頭中發(fā)送哪個值(或哪些值)。servlet 規(guī)范通過 javax.servlet.ServletRequest 類的 getLocale()getLocales() 方法自動地利用 HTTP 協(xié)議的這一功能。JSTL fmt 庫中的定制標(biāo)記又會利用這些方法來自動地確定用戶的語言環(huán)境,從而相應(yīng)地調(diào)整它們的輸出。


圖 1. 通過設(shè)置瀏覽器的語言首選項來選擇語言環(huán)境
設(shè)置瀏覽器語言首選項

但遺憾的是,不存在將用戶的時區(qū)從瀏覽器傳輸?shù)椒?wù)器的標(biāo)準(zhǔn) HTTP 請求頭。因此,那些希望自己的 Web 應(yīng)用程序?qū)r間數(shù)據(jù)進行本地化的用戶,將需要實現(xiàn)他們自己的機制,用來確定和跟蹤特定于用戶的時區(qū)。例如,在本系列文章第 2 部分“ JSTL 入門:探討 core”中所介紹的 Weblog 應(yīng)用程序包含了一種將用戶的時區(qū)首選項存儲在 cookie 中的方式。





fmt 庫

JSTL fmt 庫中的定制標(biāo)記主要分成四組。第一組允許您設(shè)置本地化上下文,其它標(biāo)記將在其中進行操作。換句話說,這組標(biāo)記允許頁面作者顯式地設(shè)置其它 fmt 標(biāo)記在格式化數(shù)據(jù)時將要使用的語言環(huán)境和時區(qū)。第二組和第三組標(biāo)記分別支持對日期和數(shù)字進行格式化和解析。最后一組標(biāo)記側(cè)重于對文本消息進行本地化。

既然我們已經(jīng)有了些基本了解,那就讓我們集中精力逐個研究這四組標(biāo)記,并演示其用法。

本地化上下文標(biāo)記

正如我們已經(jīng)討論過的那樣,JSTL 標(biāo)記在格式化數(shù)據(jù)時所使用的語言環(huán)境往往是通過查看用戶瀏覽器發(fā)送的每個 HTTP 請求所包含的 Accept-Language 頭來確定的。如果沒有提供這樣的頭,那么 JSTL 提供一組 JSP 配置變量,您可以設(shè)置這些變量以指定缺省的語言環(huán)境。如果尚未設(shè)置這些配置變量,那么就使用 JVM 的缺省語言環(huán)境,該缺省語言環(huán)境是從 JSP 容器所運行的操作系統(tǒng)中獲取的。

fmt 庫提供了其自身的定制標(biāo)記,以覆蓋這個確定用戶語言環(huán)境的過程: <fmt:setLocale> 。正如下面的代碼片段所示, <fmt:setLocale> 操作支持三個屬性:

<fmt:setLocale value="
                        expression"
                        scope="
                        scope" variant="
                        expression"/>
                        

其中只有一個屬性是必需的: value 屬性。該屬性的值應(yīng)當(dāng)是命名該語言環(huán)境的一個字符串或者是 java.util.Locale 類的一個實例。語言環(huán)境名稱是這樣組成的:小寫的兩字母 ISO 語言代碼,可選地,后面可以跟下劃線或連字符以及大寫的兩字母 ISO 國家或地區(qū)代碼。

例如, en 是英語的語言代碼, US 是美國的國家或地區(qū)代碼,因此 en_US (或 en-US )將是美式英語的語言環(huán)境名稱。類似的, fr 是法語的語言代碼, CA 是加拿大的國家或地區(qū)代碼,因此 fr_CA (或 fr-CA )是加拿大法語的語言環(huán)境名稱(請參閱 參考資料以獲取所有有效的 ISO 語言和國家或地區(qū)代碼的鏈接)。當(dāng)然,由于國家或地區(qū)代碼是可選的,因此 enfr 本身就是有效的語言環(huán)境名稱,適用于不區(qū)別這些相應(yīng)語言特定方言的應(yīng)用程序。

<fmt:setLocale> 的可選屬性 scope 用來指定語言環(huán)境的作用域。 page 作用域指出這項設(shè)置只適用于當(dāng)前頁,而 request 作用域?qū)⑺鼞?yīng)用于請求期間訪問的所有 JSP 頁面。如果將 scope 屬性設(shè)置成 session ,那么指定的語言環(huán)境被用于用戶會話期間訪問的所有 JSP 頁面。值 application 指出該語言環(huán)境適用于該 Web 應(yīng)用程序所有 JSP 頁面的全部請求和該應(yīng)用程序所有用戶的全部請求。

variant 屬性(也是可選的)允許您進一步針對特定的 Web 瀏覽器平臺或供應(yīng)商定制語言環(huán)境。例如, MACWIN 分別是 Apple Macintosh 和 Microsoft Windows 平臺的變體名。

下面的代碼片段說明了如何使用 <fmt:setLocale> 標(biāo)記來顯式指定用戶會話的語言環(huán)境設(shè)置:

<fmt:setLocale value="fr_CA" scope="session"/>
                        

JSP 容器處理完該 JSP 代碼段之后,將忽略用戶瀏覽器設(shè)置中所指定的語言首選項。

<fmt:setTimeZone> 操作像 <fmt:setLocale> 一樣,可以用來設(shè)置其它 fmt 定制標(biāo)記所使用的缺省時區(qū)值。它的語法如下所示:

<fmt:setTimeZone value="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        

<fmt:setLocale> 一樣,只有 value 屬性是必需的,但是在本例中它應(yīng)當(dāng)是時區(qū)名或 java.util.TimeZone 類的實例。

遺憾的是,對于時區(qū)命名目前還沒有任何被廣泛接受的標(biāo)準(zhǔn)。因此您可以用于 <fmt:setTimezone> 標(biāo)記的 value 屬性的時區(qū)名是特定于 Java 平臺的。您可以通過調(diào)用 java.util.TimeZone 類的 getAvailableIDs() 靜態(tài)方法來檢索有效的時區(qū)名列表。示例包括 US/Eastern 、 GMT+8Pacific/Guam

<fmt:setLocale> 的情況一樣,您可以使用可選的 scope 屬性來指出時區(qū)設(shè)置的作用域。下面的代碼演示了 <fmt:setTimeZone> 的用法,它用來指定適用于單個用戶會話的時區(qū):

<fmt:setTimeZone value="Australia/Brisbane" scope="session"/>
                        

您還可以使用 <fmt:setTimeZone> 操作將 TimeZone 實例的值存儲在限定了作用域的變量中。在本例中,您可以使用 var 屬性來命名限定了作用域的變量,用 scope 屬性來指定該變量的作用域(例如,就象這兩個屬性用在 <c:set><c:if> 操作中)。請注意,當(dāng)您以這種方式使用 <fmt:setTimeZone> 操作時,它唯一的副作用就是設(shè)置指定的變量。當(dāng)指定 var 屬性時,對于任何其它 JSTL 標(biāo)記使用什么時區(qū),不會對 JSP 環(huán)境作任何更改。

這組中的最后一個標(biāo)記是 <fmt:timeZone> 操作:

<fmt:timeZone value="
                        expression">
                        body content
                        </fmt:timeZone>
                        

<fmt:setTimeZone> 一樣,您可以使用該標(biāo)記來指定將由其它 JSTL 標(biāo)記使用的時區(qū)。但是, <fmt:timeZone> 操作的作用域僅限于其標(biāo)記體內(nèi)容。在 <fmt:timeZone> 標(biāo)記體中,由標(biāo)記的 value 屬性指定的時區(qū)覆蓋了 JSP 環(huán)境中現(xiàn)有的任何其它時區(qū)設(shè)置。

<fmt:setTimeZone> 的情況一樣, <fmt:timeZone> 標(biāo)記的 value 屬性應(yīng)當(dāng)是時區(qū)名或者是 java.util.TimeZone 實例。后面的 清單 1 中提供了一個如何使用 <fmt:timeZone> 的示例。

日期標(biāo)記

fmt 庫包含了用來與日期和時間進行交互的兩個標(biāo)記: <fmt:formatDate><fmt:parseDate> 。顧名思義, <fmt:formatDate> 用來格式化和顯示日期和時間(數(shù)據(jù) 輸出),而 <fmt:parseDate> 用來解析日期和時間值(數(shù)據(jù) 輸入)。

<fmt:formatDate> 的語法如下所示:

<fmt:formatDate value="
                        expression"
                        timeZone="
                        expression"
                        type="
                        field" dateStyle="
                        style"
                        timeStyle="
                        style"
                        pattern="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        

只有 value 屬性才是必需的。其值應(yīng)當(dāng)是 java.util.Date 類的實例,指定要進行格式化和顯示的日期和/或時間數(shù)據(jù)。

可選的 timeZone 屬性指出將要顯示哪個時區(qū)的日期和/或時間。如果沒有顯式地指定 timeZone 屬性,那么就使用周圍任何 <fmt:timeZone> 標(biāo)記所指定的時區(qū)。如果 <fmt:timeZone> 標(biāo)記的主體部分沒有包含 <fmt:formatDate> 操作,那么就使用任何適用的 <fmt:setTimeZone> 操作所設(shè)置的時區(qū)。如果沒有相關(guān)的 <fmt:setTimeZone> 操作,那么就使用 JVM 的缺省時區(qū)(也就是,專為本地操作系統(tǒng)而設(shè)置的時區(qū))。

type 屬性指出要顯示指定的 Date 實例的哪些字段,應(yīng)當(dāng)是 time 、 dateboth 。該屬性的缺省值是 date ,因此如果沒有給出 type 屬性,那么 <fmt:formatDate> 標(biāo)記(名符其實)將只顯示與 Date 實例相關(guān)的日期信息,這個信息用該標(biāo)記的 value 屬性指定。

dateStyletimeStyle 屬性分別指出應(yīng)當(dāng)如何格式化日期和時間信息。有效的樣式有 default 、 short 、 medium 、 longfull 。缺省值自然是 default ,指出應(yīng)當(dāng)使用特定于語言環(huán)境的樣式。其它四個樣式值的語義與 java.text.DateFormat 類定義的一樣。

可以使用 pattern 屬性來指定定制樣式,而不必依賴于內(nèi)置樣式。給出定制樣式后,該模式屬性的值應(yīng)當(dāng)是符合 java.text.SimpleDateFormat 類約定的模式字符串。這些模式基于用對應(yīng)的日期和時間字段代替模式內(nèi)指定的字符。例如,模式 MM/dd/yyyy 表明應(yīng)當(dāng)顯示用正斜杠分隔的兩位數(shù)的月份和日期值以及四位數(shù)的年份值。

如果指定了 var 屬性,那就把包含格式化日期的 String 值指派給指定的變量。否則, <fmt:formatDate> 標(biāo)記將寫出格式化結(jié)果。當(dāng)指定了 var 屬性后, scope 屬性指定所生成變量的作用域。

清單 1(它是本系列 第 2 部分清單 8 的擴展)包含了 <fmt:formatDate> 標(biāo)記的兩種用法。在第一種用法中, <fmt:formatDate> 只用來顯示第一個 weblog 項的創(chuàng)建時間戳記的日期部分。此外,為 dateStyle 屬性指定了一個 full 值,這樣一來所有的日期字段就將用一種特定于語言環(huán)境的格式進行顯示。


清單 1. 使用 <fmt:formatDate> 標(biāo)記來顯示日期和時間值
<table>
                        <fmt:timeZone value="US/Eastern">
                        <c:forEach items="${entryList}" var="blogEntry" varStatus="status">
                        <c:if test="${status.first}">
                        <tr><td align="left" class="blogDate">
                        <fmt:formatDate value=
                        "${blogEntry.created}" dateStyle="full"/>
                        </td></tr>
                        </c:if>
                        <tr><td align="left" class="blogTitle">
                        <c:out value="${blogEntry.title}" escapeXml="false"/>
                        </td></tr>
                        <tr><td align="left" class="blogText">
                        <c:out value="${blogEntry.text}" escapeXml="false"/>
                        <font class="blogPosted">
                        [Posted <fmt:formatDate value="${blogEntry.created}"
                        pattern="h:mm a zz"/>]
                        </font>
                        </td></tr>
                        </c:forEach>
                        </fmt:timeZone>
                        </table>
                        

<c:forEach> 循環(huán)體中,第二個 <fmt:formatDate> 操作只用來顯示每個項的創(chuàng)建日期的時間部分。在本例中, pattern 屬性用來控制時間值的格式化、并控制指定一位數(shù)的小時顯示(如果可能的話)、12 小時的時鐘和縮寫時區(qū)的輸出。輸出如圖 2 所示:


圖 2. 清單 1 中 en_US 語言環(huán)境的輸出
清單 1 中 en_US 語言環(huán)境的輸出

更準(zhǔn)確地說,用戶瀏覽器設(shè)置指定首選項是英語時,就會產(chǎn)生圖 2 中所示的輸出。但是由于 <fmt:formatDate> 對用戶語言環(huán)境敏感,所以瀏覽器首選項的改變將導(dǎo)致生成不同的內(nèi)容。例如,當(dāng)給定的首選項是法語語言環(huán)境時,則結(jié)果會如圖 3 所示:


圖 3. 清單 1 中 fr_CA 語言環(huán)境的輸出
清單 1 中 fr_CA 語言環(huán)境的輸出

<fmt:formatDate> 生成了 java.util.Date 實例的本地化字符串表示,而 <fmt:parseDate> 操作執(zhí)行相反的操作:給定一個表示日期和/或時間的字符串,它將生成相應(yīng)的 Date 對象。 <fmt:parseDate> 操作有兩種格式,如下所示:

<fmt:parseDate value="
                        expression"
                        type="
                        field" dateStyle="
                        style" timeStyle="
                        style"
                        pattern="
                        expression"
                        timeZone="
                        expression" parseLocale="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        <fmt:parseDate
                        type="
                        field" dateStyle="
                        style" timeStyle="
                        style"
                        pattern="
                        expression"
                        timeZone="
                        expression" parseLocale="
                        expression"
                        var="
                        name" scope="
                        scope">
                        body content
                        </fmt:parseDate>
                        

對于第一種格式,只有 value 屬性才是必需的,它的值應(yīng)當(dāng)是指定日期、時間或這兩者組合的字符串。對于第二種格式,沒有必需的屬性,表示要解析的值的字符串被指定為 <fmt:parseDate> 標(biāo)記必需的標(biāo)記體內(nèi)容。

type 、 dateStyle 、 timeStyle 、 patterntimeZone 屬性對 <fmt:parseDate> 和對 <fmt:formatDate> 起一樣的作用,不同之處僅在于對于前者,它們控制日期值的解析而非顯示。 parseLocale 屬性用來指定一種語言環(huán)境,將根據(jù)這種語言環(huán)境來解析該標(biāo)記的值,它應(yīng)當(dāng)是語言環(huán)境的名稱或 Locale 類的實例。

varscope 屬性用來指定限定了作用域的變量(作為 <fmt:parseDate> 的結(jié)果),將把 Date 對象賦給該變量。如果沒有給出 var 屬性,則使用 Date 類的 toString() 方法將結(jié)果寫到 JSP 頁面中。清單 2 顯示了 <fmt:parseDate> 操作的一個示例:


清單 2. 使用 <fmt:parseDate> 標(biāo)記來解析日期和時間
<c:set var="usDateString">4/1/03 7:03 PM</c:set>
                        <fmt:parseDate value="${usDateString}" parseLocale="en_US"
                        type="both" dateStyle="short" timeStyle="short"
                        var="usDate"/>
                        <c:set var="gbDateString">4/1/03 19:03</c:set>
                        <fmt:parseDate value="${gbDateString}" parseLocale="en_GB"
                        type="both" dateStyle="short" timeStyle="short"
                        var="gbDate"/>
                        <ul>
                        <li> Parsing <c:out value="${usDateString}"/> against the
                        U.S. English
                        locale yields a date of <c:out value="${usDate}"/>.</li>
                        <li> Parsing <c:out value="${gbDateString}"/> against the
                        British English
                        locale yields a date of <c:out value="${gbDate}"/>.</li>
                        </ul>
                        

清單 2 的輸出如圖 4 所示。


圖 4. 清單 2 的輸出
清單 2 的輸出

<fmt:parseDate> 所執(zhí)行的解析非常嚴格,注意這一點很重要。正如清單 2 所暗示的那樣,要解析的值必須嚴格符合特定(特定于語言環(huán)境)的樣式或模式。這當(dāng)然更加受限制。另一方面,數(shù)據(jù)的解析并不是一個非常適合于表示層的任務(wù)。對于生產(chǎn)代碼,文本輸入的驗證和轉(zhuǎn)換最好由后端代碼(比如 servlet)來處理,而不是通過 JSP 定制標(biāo)記來處理。

數(shù)字標(biāo)記

就象 <fmt:formatDate><fmt:parseDate> 標(biāo)記用于格式化和解析日期一樣, <fmt:formatNumber><fmt:parseNumber> 標(biāo)記對數(shù)字數(shù)據(jù)執(zhí)行類似的功能。

<fmt:formatNumber> 標(biāo)記用來以特定于語言環(huán)境的方式顯示數(shù)字數(shù)據(jù),包括貨幣和百分數(shù)。 <fmt:formatNumber> 操作由語言環(huán)境確定,例如,使用句點還是使用逗號來定界數(shù)字的整數(shù)和小數(shù)部分。下面是它的語法:

<fmt:formatNumber value="
                        expression"
                        type="
                        type" pattern="
                        expression"
                        currencyCode="
                        expression" currencySymbol="
                        expression"
                        maxIntegerDigits="
                        expression" minIntegerDigits="
                        expression"
                        maxFractionDigits="
                        expression" minFractionDigits="
                        expression"
                        groupingUsed="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        

<fmt:formatDate> 的情況一樣,只有 value 屬性才是必需的。它用來指定將被格式化的數(shù)值。 varscope 屬性對 <fmt:formatNumber> 操作所起的作用,如它們在 <fmt:formatDate> 中所起的作用一樣。

type 屬性的值應(yīng)當(dāng)是 number 、 currencypercentage ,并指明要對哪種類型的數(shù)值進行格式化。該屬性的缺省值是 numberpattern 屬性優(yōu)先于 type 屬性,允許對遵循 java.text.DecimalFormat 類模式約定的數(shù)值進行更精確的格式化。

當(dāng) type 屬性的值為 currency 時, currencyCode 屬性可以用來顯式地指定所顯示的數(shù)值的貨幣單位。與語言和國家或地區(qū)代碼一樣,貨幣代碼也是由 ISO 標(biāo)準(zhǔn)管理的(請參閱 參考資料以獲取所有有效的 ISO 貨幣符號代碼的鏈接)。該代碼用來確定作為已格式化值的一部分顯示的貨幣符號。

另外,您可以使用 currencySymbol 屬性來顯式地指定貨幣符號。請注意,由于 JDK 1.4 和相關(guān)的 java.util.Currency 類的引入, <fmt:formatNumber> 操作的 currencyCode 屬性優(yōu)先權(quán)超過 currencySymbol 屬性。但是對于較老版本的 JDK 而言, currencySymbol 屬性具有優(yōu)先權(quán)。

maxIntegerDigits 、 minIntegerDigits 、 maxFractionDigitsminFractionDigits 屬性用來控制小數(shù)點前后所顯示的有效數(shù)字的個數(shù)。這些屬性要求是整數(shù)值。

groupingUsed 屬性帶有布爾值并控制是否要對小數(shù)點前面的數(shù)字分組。例如,在英語語言環(huán)境中,將較大數(shù)的每三個數(shù)字分為一組,每組用逗號定界。其它語言環(huán)境用句點或空格來定界這樣的分組。該屬性的缺省值為 true

清單 3 顯示了一個簡單的貨幣示例,它本身是 清單 1 的擴展。在本例中,不指定 currencyCodecurrencySymbol 屬性。而貨幣是由語言環(huán)境設(shè)置確定的。


清單 3. 使用 <fmt:formatNumber> 標(biāo)記顯示貨幣值
<table>
                        <fmt:timeZone value="US/Eastern">
                        <c:forEach items="${entryList}" var="blogEntry"
                        varStatus="status">
                        <c:if test="${status.first}">
                        <tr><td align="left" class="blogDate">
                        <fmt:formatDate value=
                        "${blogEntry.created}" dateStyle="full"/>
                        </td></tr>
                        </c:if>
                        <tr><td align="left" class="blogTitle">
                        <c:out value="${blogEntry.title}" escapeXml="false"/>
                        </td></tr>
                        <tr><td align="left" class="blogText">
                        <c:out value="${blogEntry.text}" escapeXml="false"/>
                        <font class="blogPosted">
                        [My <fmt:formatNumber value="0.02" type="currency"/>
                        posted at <fmt:formatDate value="${blogEntry.created}"
                        pattern="h:mm a zz"/>]
                        </font>
                        </td></tr>
                        </c:forEach>
                        </fmt:timeZone>
                        </table>
                        

en_US 語言環(huán)境的輸出如圖 5 所示:


圖 5. 清單 3 的 en_US 語言環(huán)境的輸出
清單 3 的 en_US 語言環(huán)境的輸出

fr_CA 語言環(huán)境的輸出如圖 6 所示:


圖 6. 清單 3 的 fr_CA 語言環(huán)境的輸出
清單 3 的 fr_CA 語言環(huán)境的輸出

如下所示, <fmt:parseNumber> 操作解析了一個數(shù)值,該數(shù)值是通過 value 屬性或該操作的標(biāo)記體內(nèi)容以特定于語言環(huán)境的方式提供的,將結(jié)果作為 java.lang.Number 類的實例返回。 typepattern 屬性對 <fmt:parseNumber> 和對 <fmt:formatNumber> 起一樣的作用。同樣, parseLocalevarscope 屬性對 <fmt:parseNumber> 起與 <fmt:parseDate> 一樣的作用。

<fmt:parseNumber value="
                        expression"
                        type="
                        type" pattern="
                        expression"
                        parseLocale="
                        expression"
                        integerOnly="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        <fmt:parseNumber
                        type="
                        type" pattern="
                        expression"
                        parseLocale="
                        expression"
                        integerOnly="
                        expression"
                        var="
                        name" scope="
                        scope">
                        body content
                        </fmt:parseNumber>
                        

先前有關(guān) <fmt:parseDate> 的說明同樣適用于 <fmt:parseNumber> :解析數(shù)據(jù)并不是一項非常適合于表示層的任務(wù)。如果解析和驗證數(shù)據(jù)作為應(yīng)用程序業(yè)務(wù)邏輯的一部分實現(xiàn),那么軟件維護將會得到簡化。由于這個原因,通常建議大家在產(chǎn)品 JSP 頁面中避免同時使用 <fmt:parseDate><fmt:parseNumber>

只有 integerOnly 屬性才是 <fmt:parseNumber> 所獨有的。該屬性獲取一個布爾值,指出是否應(yīng)當(dāng)只解析所給值的整數(shù)部分。如果該屬性的值為 true ,那么就忽略要被解析的字符串中跟在小數(shù)點后面的任何數(shù)字。該屬性的缺省值為 false 。

消息標(biāo)記

在 JSTL 中用 <fmt:message> 標(biāo)記實現(xiàn)文本的本地化。該標(biāo)記允許您從特定于語言環(huán)境的資源束中檢索文本消息并顯示在 JSP 頁面上。而且,由于該操作利用 java.text.MessageFormat 類所提供的功能,所以可以將參數(shù)化的值替換進這樣的文本消息,以便動態(tài)地定制本地化內(nèi)容。

用于存儲特定于語言環(huán)境消息的資源束采用類或特性文件的形式,這些類或特性文件符合標(biāo)準(zhǔn)命名約定,在這種命名約定中基名和語言環(huán)境名組合在一起。例如,請研究名為 Greeting.properties 的特性文件,它駐留在我們的 weblog 應(yīng)用程序的類路徑中,該類路徑位于與 com.taglib.weblog 包相對應(yīng)的子目錄中。您可以通過在同一目錄下指定兩個新的特性文件,從而將該特性文件所描述的資源束本地化為英語和法語,通過追加相應(yīng)的語言代碼來命名。具體而言,這兩個文件應(yīng)當(dāng)分別命名為 Greeting_en.propertiesGreeting_fr.properties 。如果希望另一個本地化為加拿大法語,您可以引入第三個特性文件,在其名稱中包含了相應(yīng)的國家或地區(qū)代碼(比如 Greeting_fr_CA.properties )。

這些文件都可以定義相同的特性,但是應(yīng)當(dāng)將這些特性的值定制成對應(yīng)的語言或方言。這種方法如清單 4 和清單 5 所示,它們給出了 Greeting_en.propertiesGreeting_fr.properties 文件的樣本內(nèi)容。在這些示例中,定義了兩個已本地化的消息。它們可以通過 com.taglib.weblog.Greeting.greetingcom.taglib.weblog.Greeting.return 鍵識別。但是已經(jīng)將與這些鍵相關(guān)聯(lián)的值本地化為文件名中所確定的語言。請注意,出現(xiàn)在 com.taglib.weblog.Greeting.greeting 消息的兩個值中的 {0} 模式使已參數(shù)化的值能夠在內(nèi)容生成期間動態(tài)地插入到消息中。


清單 4. Greeting_en.properties 本地化資源束的內(nèi)容
com.taglib.weblog.Greeting.greeting=Hello {0}, and welcome to the JSTL Blog.
                        com.taglib.weblog.Greeting.return=Return
                        



清單 5. Greeting_fr.properties 本地化資源束的內(nèi)容
com.taglib.weblog.Greeting.greeting=Bonjour {0}, et bienvenue au JSTL Blog.
                        com.taglib.weblog.Greeting.return=Retournez
                        

用 JSTL 顯示這樣的本地化內(nèi)容,第一步就是指定資源束。 fmt 庫為完成這一任務(wù)提供了兩個定制標(biāo)記: <fmt:setBundle><fmt:bundle> ,它們的行為和前面介紹的 <fmt:setTimeZone><fmt:timeZone> 標(biāo)記相似。 <fmt:setBundle> 操作設(shè)置了一個缺省資源束,供 <fmt:message> 標(biāo)記在特定作用域內(nèi)使用,而 <fmt:bundle> 指定了為嵌套在其標(biāo)記體內(nèi)容中的全部和任意 <fmt:message> 操作所用的資源束。

下面的代碼片段顯示了 <fmt:setBundle> 標(biāo)記的語法。 basename 屬性是必需的,它標(biāo)識了設(shè)為缺省值的資源束。請注意, basename 屬性的值不應(yīng)當(dāng)包含任何本地化后綴或文件擴展名。清單 4 和清單 5 中給出的示例資源束的基名為 com.taglib.weblog.Greeting 。

<fmt:setBundle basename="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        

可選的 scope 屬性指明缺省資源束設(shè)置所應(yīng)用的 JSP 作用域。如果沒有顯式地指定該屬性,就假定為 page 作用域。

如果指定了可選的 var 屬性,那么將把由 basename 屬性所標(biāo)識的資源束賦給該屬性值所命名的變量。在這種情況下, scope 屬性指定變量的作用域;沒有將缺省資源束賦給相應(yīng)的 JSP 作用域。

您使用 <fmt:bundle> 標(biāo)記(其語法如下所示)在其標(biāo)記體內(nèi)容的作用域內(nèi)設(shè)置缺省資源束。和 <fmt:setBundle> 一樣,只有 basename 屬性才是必需的。您可以使用可選的 prefix 屬性來為任何嵌套的 <fmt:message> 操作的 key 值指定缺省前綴。

<fmt:bundle basename="
                        expression"
                        prefix="
                        expression">
                        body content
                        </fmt:bundle>
                        

一旦設(shè)置了資源束,真正起到顯示本地化消息作用的是 <fmt:message> 標(biāo)記。該操作支持兩種不同的語法,這取決于是否需要任何嵌套的 <fmt:param> 標(biāo)記:

<fmt:message key="
                        expression" bundle="
                        expression"
                        var="
                        name" scope="
                        scope"/>
                        <fmt:message key="
                        expression" bundle="
                        expression"
                        var="
                        name" scope="
                        scope">
                        <fmt:param value="
                        expression"/>
                        ...
                        </fmt:message>
                        

對于 <fmt:message> ,只有 key 屬性才是必需的。 key 屬性的值用來確定要顯示在資源束中定義的哪些消息。

您可以使用 bundle 屬性來指定一個顯式的資源束,用來查找由 key 屬性標(biāo)識的消息。請注意,該屬性的值必須是實際的資源束,比如當(dāng)指定 <fmt:setBundle> 操作的 var 屬性時由該操作所賦予的資源束。 <fmt:message>bundle 屬性不支持字符串值(比如 <fmt:bundle><fmt:setBundle>basename 屬性)。

如果指定了 <fmt:message>var 屬性,那么將由該標(biāo)記所生成的文本消息賦給指定的變量,而不是寫到 JSP 頁面。通常,可選的 scope 屬性用來指定由 var 屬性指定的變量的作用域。

需要的時候您可以通過使用 <fmt:param> 標(biāo)記的 value 屬性來提供文本消息的參數(shù)化值。或者,可以將該值指定為 <fmt:param> 標(biāo)記體內(nèi)容,在這種情況下省略該屬性。無論參數(shù)化值模式出現(xiàn)在消息文本中的什么地方,由 <fmt:param> 標(biāo)記指定的值都將合并到從資源束檢索的消息,這與 java.text.MessageFormat 類的行為一致。因為參數(shù)化值可以通過其下標(biāo)進行標(biāo)識,因此嵌套的 <fmt:param> 標(biāo)記的順序很重要。

<fmt:bundle><fmt:message><fmt:param> 標(biāo)記的交互作用如清單 6 所示。此處, <fmt:bundle> 標(biāo)記通過兩個嵌套的 <fmt:message> 標(biāo)記指定了要在其中檢索本地化消息的資源束。這兩個 <fmt:message> 標(biāo)記的第一個對應(yīng)于帶有一個參數(shù)化值的消息,還出現(xiàn)了對應(yīng)的用于該值的 <fmt:param> 標(biāo)記。


清單 6. 使用 <fmt:message> 標(biāo)記顯示本地化消息
<fmt:bundle basename="com.taglib.weblog.Greeting">
                        <fmt:message key="com.taglib.weblog.Greeting.greeting">
                        <fmt:param value="${user.fullName}"/>
                        </fmt:message>
                        <br>
                        <br>
                        <center>
                        <a href=
                        "<c:url value=‘/index.jsp‘/>"><fmt:message
                        key="com.taglib.weblog.Greeting.return"/></a>
                        </center>
                        </fmt:bundle>

清單 7 演示了 <fmt:bundle>prefix 屬性的用法;為 prefix 屬性提供的值在嵌套的 <fmt:message> 操作中自動地預(yù)先添加到所有 key 值上。因此清單 7 相當(dāng)于清單 6,只是清單 7 利用了這一便利的特性,使得能夠在兩個 <fmt:message> 標(biāo)記中使用縮略的 key 值。


清單 7. <fmt:bundle> 的 prefix 屬性對 <fmt:message> 標(biāo)記的影響
<fmt:bundle basename="com.taglib.weblog.Greeting"
                        prefix="com.taglib.weblog.Greeting.">
                        <fmt:message key="greeting">
                        <fmt:param value="${user.fullName}"/>
                        </fmt:message>
                        <br>
                        <br>
                        <center>
                        <a href="<c:url value=‘/index.jsp‘/>"><fmt:message key="return"/></a>
                        </center>
                        </fmt:bundle>

圖 7 和圖 8 演示了正在工作的 fmt 庫與消息相關(guān)的標(biāo)記,顯示了由清單 7 中代碼所產(chǎn)生的輸出,以及 清單 4清單 5中的本地化資源束。圖 7 顯示了當(dāng)瀏覽器首選項為英語語言環(huán)境時的結(jié)果。


圖 7. 清單 7 中 en_US 語言環(huán)境的輸出
清單 7 的 en_US 語言環(huán)境的輸出

圖 8 顯示了指定法語的語言環(huán)境的輸出。


圖 8. 清單 7 的 fr_CA 語言環(huán)境的輸出
清單 7 的 fr_CA 語言環(huán)境的輸出




回頁首


結(jié)束語

JSTL fmt 庫的定制標(biāo)記為 JSP 開發(fā)人員提供了一種對 Java 平臺的國際化 API 的簡單訪問。文本消息、數(shù)值和日期都可以用對語言環(huán)境敏感的方式進行顯示,還可以將時間調(diào)整到特定的時區(qū)??梢詮挠脩舻臑g覽器設(shè)置自動確定特定用戶的語言環(huán)境,或者由頁面作者顯式指定特定用戶的語言環(huán)境。最后,除了提供用于生成和顯示格式化數(shù)據(jù)的操作之外, fmt 庫還包含了用于解析面向數(shù)字和時間數(shù)據(jù)的定制標(biāo)記。



參考資料



關(guān)于作者

 

Mark Kolb 是一位在德克薩斯州奧斯汀工作的軟件工程師。他經(jīng)常就服務(wù)器端 Java 平臺主題在業(yè)界發(fā)表演講,他還與人合著了 Web Development with JavaServer Pages,第二版 ??梢酝ㄟ^ mak@taglib.com與 Mark 聯(lián)系。


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    丝袜破了有美女肉体免费观看| 国内真实露脸偷拍视频| 一区二区三区亚洲国产| 亚洲免费观看一区二区三区| 欧美日韩国产一级91| 亚洲男人天堂成人在线视频 | 中文字幕禁断介一区二区| 日韩偷拍精品一区二区三区| 丰满人妻熟妇乱又伦精另类视频 | 午夜精品在线视频一区| 狠狠干狠狠操在线播放| 国产精品福利一级久久| 国产中文字幕久久黄色片| 成人午夜视频精品一区| 亚洲最新av在线观看| 情一色一区二区三区四| 亚洲成人精品免费在线观看 | 成人精品一区二区三区在线| 国产又猛又大又长又粗| 美女被啪的视频在线观看| 国产精品一区二区丝袜| 日韩精品一区二区亚洲| 国产日韩欧美一区二区| 欧美大粗爽一区二区三区| 偷拍洗澡一区二区三区| 精品国产亚洲区久久露脸| 日韩精品一级片免费看| 亚洲精品有码中文字幕在线观看| 丁香六月婷婷基地伊人| 一级片黄色一区二区三区| 欧美成人精品国产成人综合| 亚洲成人精品免费在线观看| 国产亚洲不卡一区二区| 五月天丁香婷婷狠狠爱| 国产日韩精品激情在线观看| 日韩黄色大片免费在线| 国产亚洲欧美一区二区| 中文字幕久热精品视频在线| 日本高清视频在线播放| 亚洲成人久久精品国产| 玩弄人妻少妇一区二区桃花|