假設(shè)我們正在開發(fā)一個(gè)支持多國語言的web應(yīng)用程序,要求系統(tǒng)能夠根據(jù)客戶端的系統(tǒng)的語言類型返回對應(yīng)的界面:英文的操作系統(tǒng)返回英文界面,而中文的操作系統(tǒng)則返回中文界面——這便是典型的i18n國際化問題。對于有國際化要求的應(yīng)用系統(tǒng),我們不能簡單地采用硬編碼的方式編寫用戶界面信息、報(bào)錯(cuò)信息等內(nèi)容,而必須為這些需要國際化的信息進(jìn)行特殊處理。簡單來說,就是為每種語言提供一套相應(yīng)的資源文件,并以規(guī)范化命名的方式保存在特定的目錄中,由系統(tǒng)自動根據(jù)客戶端語言選擇適合的資源文件。
基礎(chǔ)知識
“國際化信息”也稱為“本地化信息”,一般需要兩個(gè)條件才可以確定一個(gè)特定類型的本地化信息,它們分別是“語言類型”和“國家/地區(qū)的類型”。如中文本地化信息既有中國大陸地區(qū)的中文,又有中國臺灣、中國香港地區(qū)的中文,還有新加坡地區(qū)的中文。java通過java.util.locale類表示一個(gè)本地化對象,它允許通過語言參數(shù)和國家/地區(qū)參數(shù)創(chuàng)建一個(gè)確定的本地化對象。
語言參數(shù)使用iso標(biāo)準(zhǔn)語言代碼表示,這些代碼是由iso-639標(biāo)準(zhǔn)定義的,每一種語言由兩個(gè)小寫字母表示。
國家/地區(qū)參數(shù)也由標(biāo)準(zhǔn)的iso國家/地區(qū)代碼表示,這些代碼是由iso-3166標(biāo)準(zhǔn)定義的,每個(gè)國家/地區(qū)由兩個(gè)大寫字母表示。
表5-2給出了一些語言和國家/地區(qū)的標(biāo)準(zhǔn)代碼:
java.util.locale是表示語言和國家/地區(qū)信息的本地化類,它是創(chuàng)建國際化應(yīng)用的基礎(chǔ)。下面給出幾個(gè)創(chuàng)建本地化對象的示例:
1
2
3
4
5
6
7
8
9
10
|
//①帶有語言和國家/地區(qū)信息的本地化對象 locale locale1 = new locale( "zh" , "cn" ); //②只有語言信息的本地化對象 locale locale2 = new locale( "zh" ); //③等同于locale("zh","cn") locale locale3 = locale.china; //④等同于locale("zh") locale locale4 = locale.chinese; //⑤獲取本地系統(tǒng)默認(rèn)的本地化對象 locale locale 5 = locale.getdefault(); |
用戶既可以同時(shí)指定語言和國家/地區(qū)參數(shù)定義一個(gè)本地化對象①,也可以僅通過語言參數(shù)定義一個(gè)泛本地化對象②。locale類中通過靜態(tài)常量定義了一些常用的本地化對象,③和④處就直接通過引用常量返回本地化對象。此外,用戶還可以獲取系統(tǒng)默認(rèn)的本地化對象,如⑤所示。
在測試時(shí),如果希望改變系統(tǒng)默認(rèn)的本地化設(shè)置,可以在啟動jvm時(shí)通過命令參數(shù)指定:java -duser.language=en -duser.region=us mytest。
本地化工具類
jdk的java.util包中提供了幾個(gè)支持本地化的格式化操作工具類:numberformat、dateformat、messageformat。下面,我們分別通過實(shí)例了解它們的用法:
numberformat:
1
2
3
4
|
locale locale = new locale( "zh" , "cn" ); numberformat currfmt = numberformat.getcurrencyinstance(locale); double amt = 123456.78 ; system.out.println(currfmt.format(amt)); |
上面的實(shí)例通過numberformat按本地化的方式對貨幣金額進(jìn)行格式化操作,運(yùn)行實(shí)例,輸出以下信息:
¥123,456.78
代碼清單5-14 dateformat
1
2
3
4
|
locale locale = new locale( "en" , "us" ); date date = new date(); dateformat df = dateformat.getdateinstance(dateformat.medium, locale); system.out.println(df.format(date)); |
通過dateformat#getdateinstance(int style,locale locale)方法按本地化的方式對日期進(jìn)行格式化操作。該方法第一個(gè)入?yún)闀r(shí)間樣式,第二個(gè)入?yún)楸镜鼗瘜ο蟆_\(yùn)行以上代碼,輸出以下信息:
jan 8, 2007
messageformat在numberformat和dateformat的基礎(chǔ)上提供了強(qiáng)大的占位符字符串的格式化功能,它支持時(shí)間、貨幣、數(shù)字以及對象屬性的格式化操作。下面的實(shí)例演示了一些常見的格式化功能:
代碼清單5-15 messageformat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//①信息格式化串 string pattern1 = "{0},你好!你于 {1} 在工商銀行存入 {2} 元。" ; string pattern2 = "at {1,time,short} on {1,date,long},{0} paid {2,number, currency}." ; //②用于動態(tài)替換占位符的參數(shù) object[] params = { "john" , new gregoriancalendar().gettime(), 1 .0e3}; //③使用默認(rèn)本地化對象格式化信息 string msg1 = messageformat.format(pattern1, params); //④使用指定的本地化對象格式化信息 messageformat mf = new messageformat(pattern2, locale.us); string msg2 = mf.format(params); system.out.println(msg1); system.out.println(msg2); |
pattern1是簡單形式的格式化信息串,通過{n}占位符指定動態(tài)參數(shù)的替換位置索引,{0}表示第一個(gè)參數(shù),{1}表示第二個(gè)參數(shù),以此類推。
pattern2格式化信息串比較復(fù)雜一些,除參數(shù)位置索引外,還指定了參數(shù)的類型和樣式。從pattern2中可以看出格式化信息串的語法是很靈活的,一個(gè)參數(shù)甚至可以出現(xiàn)在兩個(gè)地方:如 {1,time,short}表示從第二個(gè)入?yún)⒅蝎@取時(shí)間部分的值,顯示為短樣式時(shí)間;而{1,date,long}表示從第二個(gè)入?yún)⒅蝎@取日期部分的值,顯示為長樣式時(shí)間。關(guān)于messageformat更詳細(xì)的使用方法,請參見jdk的javadoc。
在②處,定義了用于替換格式化占位符的動態(tài)參數(shù),這里,我們使用到了jdk5.0自動裝包的語法,否則必須采用封裝類表示基本類型的參數(shù)值。
在③處,通過messageformat的format()方法格式化信息串。它使用了系統(tǒng)默認(rèn)的本地化對象,由于我們是中文平臺,因此默認(rèn)為locale.china。而在④處,我們顯式指定messageformat的本地化對象。
運(yùn)行上面的代碼,輸出以下信息:
引用
john,你好!你于 14-7-7 下午11:29 在工商銀行存入 1,000 元。
at 11:29 pm on july 7, 2014,john paid $1,000.00.
如果應(yīng)用系統(tǒng)中某些信息需要支持國際化功能,則必須為希望支持的不同本地化類型分別提供對應(yīng)的資源文件,并以規(guī)范的方式進(jìn)行命名。國際化資源文件的命名規(guī)范規(guī)定資源名稱采用以下的方式進(jìn)行命名:
引用
<資源名>_<語言代碼>_<國家/地區(qū)代碼>.properties
其中,語言代碼和國家/地區(qū)代碼都是可選的。<資源名>.properties命名的國際化資源文件是默認(rèn)的資源文件,即某個(gè)本地化類型在系統(tǒng)中找不到對應(yīng)的資源文件,就采用這個(gè)默認(rèn)的資源文件。<資源名>_<語言代碼>.properties命名的國際化資源文件是某一語言默認(rèn)的資源文件,即某個(gè)本地化類型在系統(tǒng)中找不到精確匹配的資源文件,將采用相應(yīng)語言默認(rèn)的資源文件。
舉一個(gè)例子:假設(shè)資源名為resource,則語言為英文,國家為美國,則與其對應(yīng)的本地化資源文件命名為resource_en_us.properties。信息在資源文件以屬性名/值的方式表示:
引用
greeting.common=how are you!
greeting.morning = good morning!
greeting.afternoon = good afternoon!
對應(yīng)語言為中文,國家/地區(qū)為中國大陸的本地化資源文件則命名為resource_zh_ cn.properties,資源文件內(nèi)容如下:
greeting.common=\u60a8\u597d\uff01
greeting.morning=\u65e9\u4e0a\u597d\uff01
greeting.afternoon=\u4e0b\u5348\u597d\uff01
本地化不同的同一資源文件,雖然屬性值各不相同,但屬性名卻是相同的,這樣應(yīng)用程序就可以通過locale對象和屬性名精確調(diào)用到某個(gè)具體的屬性值了。
讀者可能已經(jīng)注意到,上面中文的本地化資源文件內(nèi)容采用了特殊的編碼表示中文字符,這是因?yàn)橘Y源文件對文件內(nèi)容有嚴(yán)格的要求:只能包含ascii字符。所以必須將非ascii字符的內(nèi)容轉(zhuǎn)換為unicode代碼的表示方式。如上面中文的resource_zh_cn.properties資源文件的三個(gè)屬性值分別是“您好!”、“早上好!”和“下午好!”三個(gè)中文字符串對應(yīng)的unicode代碼串。
如果在應(yīng)用開發(fā)時(shí),直接采用unicode代碼編輯資源文件是很不方便的,所以,通常我們直接使用正常的方式編寫資源文件,在測試或部署時(shí)再采用工具進(jìn)行轉(zhuǎn)換。jdk在bin目錄下為我們提供了一個(gè)完成此項(xiàng)功能的native2ascii工具,它可以將中文字符的資源文件轉(zhuǎn)換為unicode代碼格式的文件,命令格式如下:
引用
native2ascii [-reverse] [-encoding 編碼] [輸入文件 [輸出文件]]
resource_zh_cn.properties包含中文字符并且以utf-8進(jìn)行編碼,假設(shè)將該資源文件放到d:\目錄下,通過下面的命令就可以將其轉(zhuǎn)換為unicode代碼的形式:
引用
d:\>native2ascii -encoding utf-8 d:\resource_zh_cn.properties
d:\resource_zh_cn_1.properties
由于原資源文件采用utf-8編碼,所以必須顯式通過-encoding指定編碼格式。
引用
通過native2ascii命令手工轉(zhuǎn)換資源文件,不但在操作上不方便,轉(zhuǎn)換后資源文件中的屬性內(nèi)容由于采用了ascii編碼,閱讀起來也不方便。很多ide開發(fā)工具都有屬性編輯器的插件,插件會自動將資源文件內(nèi)容轉(zhuǎn)換為ascii形式的編碼,同時(shí)以正常的方式閱讀和編輯資源文件的內(nèi)容,這給開發(fā)和維護(hù)帶來了很大的便利。對于myeclipse來說,使用myeclipse properties editor編輯資源屬性文件;對于intellij idea來說,無須安裝任何插件就自然支持資源屬性文件的這種編輯方式了。
如果應(yīng)用程序中擁有大量的本地化資源文件,直接通過傳統(tǒng)的file操作資源文件顯然太過笨拙。java為我們提供了用于加載本地化資源文件的方便類java.util.resourceboundle。
resourceboundle為加載及訪問資源文件提供便捷的操作,下面的語句從相對于類路徑的目錄中加載一個(gè)名為resource的本地化資源文件:
resourcebundle rb = resourcebundle.getbundle("com/baobaotao/i18n/resource", locale)
通過以下的代碼即可訪問資源文件的屬性值:
rb.getstring("greeting.common")
來看下面的實(shí)例:
代碼清單5-16 resourceboundle
1
2
3
4
|
resourcebundle rb1 = resourcebundle.getbundle( "com/baobaotao/i18n/resource" , locale.us); resourcebundle rb2 = resourcebundle.getbundle( "com/baobaotao/i18n/resource" , locale.china); system.out.println( "us:" +rb1.getstring( "greeting.common" )); system.out.println( "cn:" +rb2.getstring( "greeting.common" )); |
rb1加載了對應(yīng)美國英語本地化的resource_en_us.properties資源文件;而rb2加載了對應(yīng)中國大陸中文的resource_zh_cn.properties資源文件。運(yùn)行上面的代碼,將輸出以下信息:
引用
us:how are you!
cn:你好!
加載資源文件時(shí),如果不指定本地化對象,將使用本地系統(tǒng)默認(rèn)的本地化對象。所以,在中文系統(tǒng)中,resourcebundle.getbundle("com/baobaotao/i18n/resource")語句也將返回和代碼清單5-14中rb2相同的本地化資源。
resourcebundle在加載資源時(shí),如果指定的本地化資源文件不存在,它按以下順序嘗試加載其他的資源:本地系統(tǒng)默認(rèn)本地化對象對應(yīng)的資源→默認(rèn)的資源。上面的例子中,假設(shè)我們使用resourcebundle.getbundle("com/baobaotao/i18n/resource",locale.canada)加載資源,由于不存在resource_en_ca.properties資源文件,它將嘗試加載resource_zh_cn.properties的資源文件,假設(shè)resource_zh_cn.properties資源文件也不存在,它將繼續(xù)嘗試加載resource.properties的資源文件,如果這些資源都不存在,將拋出java.util.missingresourceexception異常。
在資源文件中使用格式化串
在上面的資源文件中,屬性值都是一般的字符串,它們不能結(jié)合運(yùn)行時(shí)的動態(tài)參數(shù)構(gòu)造出靈活的信息,而這種需求是很常見的。要解決這個(gè)問題很簡單,只須使用帶占位符的格式化串作為資源文件的屬性值并結(jié)合使用messageformat就可以滿足要求了。
上面的例子中,我們僅向用戶提供一般性問候,下面我們對資源文件進(jìn)行改造,通過格式化串讓問候語更具個(gè)性化:
引用
greeting.common=how are you!{0},today is {1}
greeting.morning = good morning!{0},now is {1 time short}
greeting.afternoon = good afternoon!{0} now is {1 date long}
將該資源文件保存在fmt_resource_en_us.properties中,按照同樣的方式編寫對應(yīng)的中文本地化資源文件fmt_resource_zh_cn.properties。
下面,我們聯(lián)合使用resourceboundle和messageformat得到美國英文的本地化問候語:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//①加載本地化資源 resourcebundle rb1 = resourcebundle.getbundle( "com/baobaotao/i18n/fmt_ resource" ,locale.us); resourcebundle rb2 = resourcebundle.getbundle( "com/baobaotao/i18n/fmt_ resource" ,locale.china); object[] params = { "john" , new gregoriancalendar().gettime()}; string str1 = new messageformat(rb1.getstring( "greeting.common" ),locale.us).format(params); string str2 = new messageformat(rb2.getstring( "greeting.morning" ),locale.china).format(params); string str3 = new messageformat(rb2.getstring( "greeting.afternoon" ),locale.china).format(params); system.out.println(str1); system.out.println(str2); system.out.println(str3); |
運(yùn)行以上的代碼,將輸出以下信息:
引用
how are you!john,today is 1/9/07 4:11 pm
早上好!john,現(xiàn)在是下午4:11
下午好!john,現(xiàn)在是2007年1月9日
messagesource
spring定義了訪問國際化信息的messagesource接口,并提供了幾個(gè)易用的實(shí)現(xiàn)類。首先來了解一下該接口的幾個(gè)重要方法:
string getmessage(string code, object[] args, string defaultmessage, locale locale)
code表示國際化資源中的屬性名;args用于傳遞格式化串占位符所用的運(yùn)行期參數(shù);當(dāng)在資源找不到對應(yīng)屬性名時(shí),返回defaultmessage參數(shù)所指定的默認(rèn)信息;locale表示本地化對象;
string getmessage(string code, object[] args, locale locale) throws nosuchmessageexception
與上面的方法類似,只不過在找不到資源中對應(yīng)的屬性名時(shí),直接拋出nosuchmessageexception異常;
string getmessage(messagesourceresolvable resolvable, locale locale) throws nosuchmessageexception
messagesourceresolvable 將屬性名、參數(shù)數(shù)組以及默認(rèn)信息封裝起來,它的功能和第一個(gè)接口方法相同。
messagesource的類結(jié)構(gòu)
messagesource分別被hierarchicalmessagesource和applicationcontext接口擴(kuò)展,這里我們主要看一下hierarchicalmessagesource接口的幾個(gè)實(shí)現(xiàn)類,如圖5-7所示:
hierarchicalmessagesource接口添加了兩個(gè)方法,建立父子層級的messagesource結(jié)構(gòu),類似于前面我們所介紹的hierarchicalbeanfactory。該接口的setparentmessagesource (messagesource parent)方法用于設(shè)置父messagesource,而getparentmessagesource()方法用于返回父messagesource。
hierarchicalmessagesource接口最重要的兩個(gè)實(shí)現(xiàn)類是resourcebundlemessagesource和reloadableresourcebundlemessagesource。它們基于java的resourcebundle基礎(chǔ)類實(shí)現(xiàn),允許僅通過資源名加載國際化資源。reloadableresourcebundlemessagesource提供了定時(shí)刷新功能,允許在不重啟系統(tǒng)的情況下,更新資源的信息。staticmessagesource主要用于程序測試,它允許通過編程的方式提供國際化信息。而delegatingmessagesource是為方便操作父messagesource而提供的代理類。
resourcebundlemessagesource
該實(shí)現(xiàn)類允許用戶通過beanname指定一個(gè)資源名(包括類路徑的全限定資源名),或通過beannames指定一組資源名。在前面的代碼清單中,我們通過jdk的基礎(chǔ)類完成了本地化的操作,下面我們使用resourcebundlemessagesource來完成相同的任務(wù)。讀者可以比較兩者的使用差別,并體會spring所提供的國際化處理功能所帶給我們的好處:
通過resourcebundlemessagesource配置資源
1
2
3
4
5
6
7
8
9
|
<bean id= "myresource" class = "org.springframework.context.support.resourcebundlemessagesource" > <!--①通過基名指定資源,相對于類根路徑--> <property name= "basenames" > <list> <value>com/baobaotao/i18n/fmt_resource</value> </list> </property> </bean> |
啟動spring容器,并通過messagesource訪問配置的國際化資源,如下代碼清單所示:
代碼清單5-19 訪問國際化消息:resourcebundlemessagesource:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
string[] configs = { "com/baobaotao/i18n/beans.xml" }; applicationcontext ctx = new classpathxmlapplicationcontext(configs); //①獲取messagesource的bean messagesource ms = (messagesource)ctx.getbean( "myresource" ); object[] params = { "john" , new gregoriancalendar().gettime()}; //②獲取格式化的國際化信息 string str1 = ms.getmessage( "greeting.common" ,params,locale.us); string str2 = ms.getmessage( "greeting.morning" ,params,locale.china); string str3 = ms.getmessage( "greeting.afternoon" ,params,locale.china); system.out.println(str1); system.out.println(str2); system.out.println(str3); |
比較代碼清單中的代碼,我們發(fā)現(xiàn)最主要的區(qū)別在于我們無須再分別加載不同語言、不同國家/地區(qū)的本地化資源文件,僅僅通過資源名就可以加載整套的國際化資源文件。此外,我們無須顯式使用messageformat操作國際化信息,僅通過messagesource# getmessage()方法就可以完成操作了。這段代碼的運(yùn)行結(jié)果與前面的代碼的運(yùn)行結(jié)果完全一樣。
reloadableresourcebundlemessagesource
前面,我們提到該實(shí)現(xiàn)類比之于resourcebundlemessagesource的唯一區(qū)別在于它可以定時(shí)刷新資源文件,以便在應(yīng)用程序不重啟的情況下感知資源文件的變化。很多生產(chǎn)系統(tǒng)都需要長時(shí)間持續(xù)運(yùn)行,系統(tǒng)重啟會給運(yùn)行帶來很大的負(fù)面影響。這時(shí),通過該實(shí)現(xiàn)類就可以解決國際化信息更新的問題。請看下面的配置:
通過reloadableresourcebundlemessagesource配置資源:
xml代碼
1
2
3
4
5
6
7
8
9
10
|
<bean id= "myresource" lass= "org.springframework.context.support.reloadableresourcebundlemessagesource" > <property name= "basenames" > <list> <value>com/baobaotao/i18n/fmt_resource</value> </list> </property> <!--① 刷新資源文件的周期,以秒為單位--> <property name= "cacheseconds" value= "5" /> </bean> |
在上面的配置中,我們通過cacheseconds屬性讓reloadableresourcebundlemessagesource每5秒鐘刷新一次資源文件(在真實(shí)的應(yīng)用中,刷新周期不能太短,否則頻繁的刷新將帶來性能上的負(fù)面影響,一般不建議小于30分鐘)。cacheseconds默認(rèn)值為-1表示永不刷新,此時(shí),該實(shí)現(xiàn)類的功能就蛻化為resourcebundlemessagesource的功能。
我們編寫一個(gè)測試類對上面配置的reloadableresourcebundlemessagesource進(jìn)行測試:
代碼清單5-21 刷新資源:reloadableresourcebundlemessagesource
1
2
3
4
5
6
7
8
9
10
11
|
string[] configs = { "com/baobaotao/i18n/beans.xml" }; applicationcontext ctx = new classpathxmlapplicationcontext(configs); messagesource ms = (messagesource)ctx.getbean( "myresource" ); object[] params = { "john" , new gregoriancalendar().gettime()}; for ( int i = 0 ; i < 2 ; i++) { string str1 = ms.getmessage( "greeting.common" ,params,locale.us); system.out.println(str1); thread.currentthread().sleep( 20000 ); //①模擬程序應(yīng)用,在此期間,我們更改資源文件 } |
在①處,我們讓程序睡眠20秒鐘,在這期間,我們將fmt_resource_zh_cn.properties資源文件的greeting.common鍵值調(diào)整為:
引用
---how are you!{0},today is {1}---
我們將看到兩次輸出的格式化信息分別對應(yīng)更改前后的內(nèi)容,也即本地化資源文件的調(diào)整被自動生效了:
引用
how are you!john,today is 1/9/07 4:55 pm
---how are you!john,today is 1/9/07 4:55 pm---
容器級的國際化信息資源
在如圖5-7所示的messagesource類圖結(jié)構(gòu)中,我們發(fā)現(xiàn)applicationcontext實(shí)現(xiàn)了messagesource的接口。也就是說applicationcontext的實(shí)現(xiàn)類本身也是一個(gè)messagesource對象。
將applicationcontext和messagesource整合起來,乍一看挺讓人費(fèi)解的,spring這樣設(shè)計(jì)的意圖究竟是什么呢?原來spring認(rèn)為:在一般情況下,國際化信息資源應(yīng)該是容器級。我們一般不會將messagesource作為一個(gè)bean注入到其他的bean中,相反messagesource作為容器的基礎(chǔ)設(shè)施向容器中所有的bean開放。只要我們考察一下國際化信息的實(shí)際消費(fèi)場所就更能理解spring這一設(shè)計(jì)的用意了。國際化信息一般在系統(tǒng)輸出信息時(shí)使用,如spring mvc的頁面標(biāo)簽,控制器controller等,不同的模塊都可能通過這些組件訪問國際化信息,因此spring就將國際化消息作為容器的公共基礎(chǔ)設(shè)施對所有組件開放。
既然一般情況下我們不會直接通過引用messagesource bean使用國際信息,那如何聲明容器級的國際化信息呢?我們其實(shí)在5.1.1節(jié)講解spring容器的內(nèi)部工作機(jī)制時(shí)已經(jīng)埋下了伏筆:在介紹容器啟動過程時(shí),我們通過代碼清單5-1對spring容器啟動時(shí)的步驟進(jìn)行剖析,④處的initmessagesource()方法所執(zhí)行的工作就是初始化容器中的國際化信息資源:它根據(jù)反射機(jī)制從beandefinitionregistry中找出名稱為“messagesource”且類型為org.springframework.context.messagesource的bean,將這個(gè)bean定義的信息資源加載為容器級的國際化信息資源。請看下面的配置:
代碼清單5-22 容器級資源的配置
1
2
3
4
5
6
7
8
9
|
<!--①注冊資源bean,其bean名稱只能為messagesource --> <bean id= "messagesource" class = "org.springframework.context.support.resourcebundlemessagesource" > <property name= "basenames" > <list> <value>com/baobaotao/i18n/fmt_resource</value> </list> </property> </bean> |
下面,我們通過applicationcontext直接訪問國際化信息,如下代碼清單所示:
代碼清單5-23 通過applicationcontext訪問國際化信息
java代碼
1
2
3
4
5
6
7
8
9
|
string[] configs = { "com/baobaotao/i18n/beans.xml" }; applicationcontext ctx = new classpathxmlapplicationcontext(configs); //①直接通過容器訪問國際化信息 object[] params = { "john" , new gregoriancalendar().gettime()}; string str1 = ctx.getmessage( "greeting.common" ,params,locale.us); string str2 = ctx.getmessage( "greeting.morning" ,params,locale.china); system.out.println(str1); system.out.println(str2); |
運(yùn)行以上代碼,輸出以下信息:
引用
how are you!john,today is 1/9/07 5:24 pm
早上好!john,現(xiàn)在是下午5:24
假設(shè)messagesource bean名字沒有命名為“messagesource”,以上代碼將拋出nosuchmessageexception異常。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。