SpringMVC源碼學(xué)習(xí)與實踐(二):LocaleResolver

LocaleResolver簡介

? ? localeResolver是當(dāng)前的區(qū)域解析器提澎,簡單來說我們可以通過這個接口來實現(xiàn)國際化。

官方介紹

1)基于web的區(qū)域設(shè)置解析策略接口

2)通過請求進(jìn)行區(qū)域設(shè)置解析

3)可以使用基于request虱朵、session莉炉、cookies實現(xiàn)。

默認(rèn)的實現(xiàn)是AcceptHeaderLocaleResolver【通過HTTP頭提供的信息進(jìn)行設(shè)置】

4)使用RequestContext.getLocale()檢索controller或views中的當(dāng)前區(qū)域設(shè)置

點擊查看詳細(xì)文檔介紹

接口分析

下面列出這個類的核心方法


LocaleResolver接口核心方法

可以看出這個接口的很簡單梆暮,含義也很清晰:

1)Locale resolveLocale(request):解析當(dāng)前區(qū)域語言绍昂,可以返回當(dāng)前的Locale;

2)void setLocale(request, response,locale)改變當(dāng)前的Locale窘游;

繼承結(jié)構(gòu)分析

我們來看下LocaleResovler的類成繼承結(jié)構(gòu)以及Spring提供給了我們哪些默認(rèn)的實現(xiàn)類:


LocaleResolver繼承結(jié)構(gòu)

可以看到默認(rèn)提供了4個實現(xiàn)類,下面分別介紹一下:

1.AcceptHeaderLocaleResolver

通過獲取http請求頭里邊的“accept-language”來設(shè)置區(qū)域信息贪嫂,因為我們無法通過改變客戶端傳入的header的頭信息來改變區(qū)域設(shè)置,所以這個類不支持修改Locale(即使這次能修改成功力崇,下次傳過來的header也還是原來的斗塘,所以spring在這個類里的resolveLocale方法做了拋出異常的操作)馍盟。

2.CookieLocaleResolver

這個類繼承了LocaleContextResolver接口,這個接口對頂級接口做了一些擴展贞岭,支持設(shè)置/返回Locale的context上下文搓侄,上下文中保存更多的信息例如:當(dāng)前的locale或者timeZone(典型的實現(xiàn)為TimeZoneAwareLocaleConext同時包含當(dāng)前l(fā)ocale和timeZone)

接下來繼續(xù)說這個CookieLocaleResolver類,簡單來說休讳,我們可以通過修改cookie里邊的區(qū)域值然后返回給客戶端,下次客戶端傳過來的時候就是我們上次修改后的區(qū)域值,這樣來達(dá)到動態(tài)改變locale的目的俊柔。

3.FixedLocaleResolver

這個類繼承了AbstractLocaleResolver和AbstractLocaleContextResolver兩個抽象類:

1) AbstractLocaleResolver

擴展了LocaleResolver:支持設(shè)置/返回默認(rèn)locale的能力;

2) AbstractLocaleContextResolver

繼承自AbstractLocaleResolver雏婶,在AbstractLocaleResolver的基礎(chǔ)上提供了設(shè)置默認(rèn)時區(qū)的能力;

再回來說這個類酵紫,它是從JVM獲取默認(rèn)的locale,并且不支持修改locale奖地,感覺實際用處不是很大。

4.SessionLocaleResolver

這個類是我們比較常用的類参歹,它比較靈活,因為它支持我們從session里邊去設(shè)置/獲取locale犬庇,同時它也實現(xiàn)了AbstractLocaleResolver和AbstractLocaleContextResolver接口,擁有獲取locale上下文的能力[同F(xiàn)ixedLocaleResolver]

實踐操作

下面來實際操作一下如何在項目中使用session來改變locale(文章最后補充了一種簡單的設(shè)置locale方式)

1.首先創(chuàng)建需要的i18n文件:

國際化資源文件
messages.properties
messages_en_US.properties
messages_zh_CN.properties

2.創(chuàng)建view視圖文件

index.html視圖文件

3.注冊SessionLocaleResolver


注冊SessionLocaleResolver

????創(chuàng)建SessionLocaleResolver注入spring上下文中(如果不定義springboot默認(rèn)使用AcceptHeaderLocaleResolver);

4.注入controller,寫測試接口

1.?注入localeResolver

5.瀏覽器輸入請求地址

請求為locale=zh_CN
請求為locale=en_US

6.輸入查看接口的地址


查看接口localeResolver

從測試結(jié)果來看欢峰,我們通過改變locale參數(shù),然后訪問localeResult接口闯狱,輸出的結(jié)果都會是當(dāng)前的設(shè)置的語言來解析的,除非再次改變locale參數(shù)哄孤。什么意思呢?就是說每次我們改變locale值瘦陈,就已經(jīng)保存在session里邊了。后續(xù)的請求都是去session里邊獲取locale然后去解析對應(yīng)的*. Properties文件里邊的“welcome”;

源碼分析

? ? 總的過程為:AbstractLocaleContextResolver默認(rèn)實現(xiàn)了頂級接口的setLocale方法晨逝,但是它調(diào)用了從LocaleContextResolver接口繼承的setLocaleContext()方法懦铺,而這個方法是在SessionLocaleResolver里邊實現(xiàn)的;

AbstractLocaleContextResolver的setLocale()方法


SessionLocaleResolver的setLocaleContext()方法

我們在程序里調(diào)用localeResolver.setLocale()方法時冬念,Spring會去查找實現(xiàn)了setLocale()的子類,雖然我們注入的是sessionLocaleResolver急前,但是它并沒有實現(xiàn)這個方法,而是它的父類AbstractLocaleContextResolver實現(xiàn)了setLocale()方法裆针,找到這個實現(xiàn)方法以后發(fā)現(xiàn)方法里又調(diào)用了setLocaleContext()方法,而實現(xiàn)這個方法的子類就是SessionLocaleResolver世吨,這樣實際的職責(zé)又回到了這個類里邊。我們發(fā)現(xiàn)它確實是在session里邊設(shè)置了locale另假。

那么Spring為什么要這么設(shè)計呢?直接在SessionLocaleResolver里邊實現(xiàn)setLocale方法不行嗎边篮?我認(rèn)為核心應(yīng)該就是這個localeContext戈轿,因為localeContext里邊包含了locale和timeZone,它倆最終定義包含在了AbstractLocaleContextResolver里邊思杯。但是這個類是個抽象類,它并沒有能力去設(shè)置locale色乾,而是把設(shè)置的方法預(yù)留了出來(也就是繼承自接口LocaleContextResolver.setLocaleContext()方法),它只需要去調(diào)用子類實現(xiàn)的這個方法去設(shè)置就好了暖璧。即:只要繼承了AbstractLocaleContextResolver這個抽象類,那么你肯定就得實現(xiàn)setLocaleContext()方法澎办,具體從哪里來的localeConext它就不管了。這樣代碼層次就會非常的清晰局蚀,印證了設(shè)計原則里邊的開閉原則:對修改關(guān)閉對擴展開放。

resolveLocale()方法就不在說了過程比較簡單琅绅,跟設(shè)置過程一樣。

簡單方法設(shè)置locale:

上面我是手動設(shè)置locale的千扶,除此之外Spring為我們提供了一個攔截器LocaleChangeInterceptor,通過這個攔截器可以達(dá)到自動設(shè)置locale的目的

注冊LocaleChangeInterceptor

步驟:其實我們只需創(chuàng)建一個這樣攔截器县貌,并且指定保存locale的參數(shù)就可以了(默認(rèn)通過request里邊的“l(fā)ocale”參數(shù));

原理:在每個request請求來的時候煤痕,通過攔截request獲取里邊的locale參數(shù),來進(jìn)行自動設(shè)置locale摆碉。大致源碼如下:

自動設(shè)置locale

結(jié)束語:

1) localeResolver設(shè)置/獲取locale的核心方法是setLocale()和resovleLoccale()兩個方法;

2) LocaleContext是locale的上下文典型實現(xiàn)為SimpleTimeZoneAwareLocaleContext包含默認(rèn)的lcoale和timeZone;如果我們想自定義localeContext支持包含一些其它信息巷帝,可以通過繼承SimpleLocaleContext實現(xiàn);

3) 實現(xiàn)locale的設(shè)置兩種方式楞泼,手動設(shè)置locale和通過攔截器獲取請求參數(shù)自動設(shè)置,推薦第二種堕阔;


下節(jié)預(yù)覽:上面我們學(xué)習(xí)了比較簡單的localResolver接下來繼續(xù)看一下相對復(fù)雜點兒的viewResolver,它是mvc里邊的視圖層超陆,我們最終看到的html頁面的就跟這個viewResolver有關(guān)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末张漂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子航攒,更是在濱河造成了極大的恐慌,老刑警劉巖屎债,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盆驹,居然都是意外死亡,警方通過查閱死者的電腦和手機躯喇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廉丽,“玉大人,你說我怎么就攤上這事正压。” “怎么了焦履?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嘉裤。 經(jīng)常有香客問我,道長屑宠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任典奉,我火速辦了婚禮,結(jié)果婚禮上秋柄,老公的妹妹穿的比我還像新娘。我一直安慰自己骇笔,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布懦傍。 她就那樣靜靜地躺著,像睡著了一般粗俱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寸认,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音偏塞,去河邊找鬼。 笑死灸叼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庆捺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼捉腥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了你画?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤立磁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后剥槐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡颅崩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沿后。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡尖滚,死狀恐怖喉刘,靈堂內(nèi)的尸體忽然破棺而出漆弄,到底是詐尸還是另有隱情,我是刑警寧澤撼唾,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站倒谷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏渤愁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一猴伶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧他挎,春花似錦筝尾、人聲如沸筹淫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至殊霞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绷蹲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工祝钢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拦英。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像疤估,于是被迫代替她去往敵國和親霎冯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容