Spring MVC中,當DispatcherServlet初始化的時候,會解析一個LocaleResolver接口的實現類,這個實現類就是用來解析國際化的。
一、國際化解析器
Spring MVC中提供了以下四個實現類:
- AcceptHeaderLocaleResolver:spring默認的區域解析器,它通過校驗http請求的accept-language頭部來解析區域。這個頭是由web瀏覽器根據底層操作系統的區域設置,這個區域無法改變用戶的區域,所以只能根據操作系統設置而獲取,一般不使用;
- FixedLocaleResolver:使用固定的locale國際化,也是不可修改;
- CookieLocaleResolver:根據cookie數據獲取國際化數據,但是如果用戶禁止或沒有設置cookie,就會根據http頭中的accept-language來獲取;
- SessionLocaleResolver:根據session進行國際化,即根據用戶設置session的變量進行讀取,所以它是可變的,也是使用最多的;
為了修改國際化,Spring MVC還提供了一個攔截器-LocaleChangeInterceptor,通過它可以獲取參數,然后根據參數來改變區域;
它的配置方式如下:
1、JAVA配置方式
1⃣️配置CookieLocaleResolver
1 /** 2 * 配置CookieLocaleResolver 3 * bean名稱必須是localeResolver 4 * 5 * @return 6 */ 7 @Bean(name = "localeResolver") 8 public CookieLocaleResolver initCookieLocaleResolver() { 9 CookieLocaleResolver clr = new CookieLocaleResolver(); 10 // 設置cookie名稱 11 clr.setCookieDomain("lang"); 12 // 設置超時秒數 13 clr.setCookieMaxAge(3600); 14 // 默認使用簡體中文 15 clr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); 16 return clr; 17 }
2⃣️配置SessionLocaleResolver
1 /** 2 * 配置SessionLocaleResolver 3 * bean名稱必須是localeResolver 4 * 5 * @return 6 */ 7 @Bean(name = "localeResolver") 8 public SessionLocaleResolver initSessionLocaleResolver() { 9 SessionLocaleResolver slr = new SessionLocaleResolver(); 10 // 默認使用簡體中文 11 slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); 12 return slr; 13 }
2、XML配置方式
1⃣️配置CookieLocaleResolver
1 <!--第一種:配置cookie國際化解析器 --> 2 <bean id="localeResolver" 3 class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> 4 <!-- cookie變量的名稱 --> 5 <property name="cookieName" value="lang" /> 6 <!-- cookie超時時間 --> 7 <property name="cookieMaxAge" value="20" /> 8 <!-- 默認使用簡體中文 --> 9 <property name="defaultLocale" value="zh_CN" /> 10 </bean>
2⃣️配置SessionLocaleResolver
1 <!--第一種:配置session國際化解析器 --> 2 <bean id="localResolver" 3 class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> 4 因為session有其自身定義的超時時間和編碼,所以此處不需要設置 5 <property name="defaultLocale" value="zh_CN" /> 6 </bean>
注意⚠️:
- 不管配置哪種解析器,bean的名稱都必須是localeResolver,這是Spring MVC默認的名稱,不能修改,否則找不到;
- session有其自定義的超時時間,所以無需配置;
二、國際化文件加載
在實現國際化之前,首先要加載相關的資源文件,即消息源,這個功能由Spring MVC提供的MessageSource接口完成,並且有四個非抽象的實現類:
- StaticMessageSource:靜態消息源;
- DelegatingMessageSource:實現的是代理功能;
- ResourceBundleMessageSource:由JDK提供的Bundle實現,只能把文件放置在對應的類路徑下,不具備熱加載功能,只有重啟系統才能重新加載;
- ReloadavleResourceBundleMessageSource:可以把文件放置在任何地方,並且在不重啟系統的前提下也能重新加載資源文件,這樣就可以在程序運行期修改並重新加載資源文件;
其實在配置國際化解析器之前還要配置消息源,下面介紹如何配置,還是有兩種方式:
1、JAVA方式配置消息源
1⃣️配置ResourceBundleMessageSource
1 /** 2 * 配置ResourceBundleMessageSource消息源 3 * bean名稱必須為messageSource 4 * 5 * @return 6 */ 7 @Bean(name = "messageSource") 8 public MessageSource initResourceBundleMessageSource() { 9 ResourceBundleMessageSource rbms = new ResourceBundleMessageSource(); 10 rbms.setDefaultEncoding("UTF-8"); 11 rbms.setBasename("msg"); 12 return rbms; 13 }
2⃣️配置ReloadableResourceBundleMessageSource
1 /** 2 * 配置ReloadableResourceBundleMessageSource消息源 3 * bean名稱必須為messageSource 4 * 5 * @return 6 */ 7 @Bean(name = "messageSource") 8 public MessageSource initReloadableResourceBundleMessageSource() { 9 ReloadableResourceBundleMessageSource rrbms = new ReloadableResourceBundleMessageSource(); 10 rrbms.setDefaultEncoding("UTF-8"); 11 // 因為是熱加載,所以需要加上classpath 12 rrbms.setBasename("classpath:msg"); 13 // 設置刷新的秒數,即多長時間刷新一次 14 rrbms.setCacheSeconds(1800); 15 // 設置刷新的毫秒數 16 rrbms.setCacheMillis(1800000); 17 return rrbms; 18 }
2、XML方式配置消息源
1⃣️配置ResourceBundleMessageSource
1 <!--第一種方式:配置ResourceBundleMessageSource:這種方式只能把資源文件放到指定的路徑下,不能熱加載,需要重啟系統才能加載它 --> 2 <bean id="messageResource" 3 class="org.springframework.context.support.ResourceBundleMessageSource"> 4 <property name="defaultEncoding" value="UTF-8" /> 5 <property name="basename" value="msg" /> 6 </bean>
2⃣️配置ReloadableResourceBundleMessageSource
1 <!--第二種方式:配置ReloadableResourceBundleMessageSource:這種方式只能把資源文件放到任何位置,不需要重啟就能加載文件,並且可以設置刷新時間 --> 2 <bean id="messageSource" 3 class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 4 <!-- 默認編碼方式 --> 5 <property name="defaultEncoding" value="UTF-8" /> 6 <!-- 資源文件的前綴:多了一個classpath,如果資源文件在一個文件夾下,還要加上文件夾路徑,否則報錯 --> 7 <property name="basename" value="classpath:message/msg" /> 8 <!-- 刷新時間 --> 9 <property name="cacheSeconds" value="3600" /> 10 </bean>
需要注意以下幾點:
- 無論何種方式配置何種消息源,bean的名稱必須是messageSource;
- ReloadableResourceBundleMessageSource可以熱加載,所以需要配置刷新時間,並且配置資源文件的前綴時需要加classpath,如果資源文件在classpath的某個文件夾下,還需要加上文件夾的名稱;
三、配置攔截器
通過請求參數去改變國際化的值時,可以使用Spring提供的攔截器LocaleChangeInterceptor,它繼承了HandlerInterceptorAdapter,通過覆蓋它的preHandle方法,然后使系統所配置的LocaleResolver實現國際化,這個一般是配置在Spring MVC的配置文件中:
1 <!-- 配置國際化攔截器 --> 2 <mvc:interceptors> 3 <mvc:interceptor> 4 <mvc:mapping path="/**" /> 5 <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> 6 <property name="paramName" value="language" /> 7 </bean> 8 </mvc:interceptor> 9 </mvc:interceptors>
其中:
- <mvc:mapping>的path屬性值配置成/**,這樣就能攔截所有/請求及其子路徑中的請求了;
- 攔截器的屬性paramName的值就是url中傳過來的參數,如language=zh_CN或language=en_US等;
至此,國際化中所有的配置都已經介紹完畢,下一篇文章將舉一個實現過程的例子。