SpringMVC之源碼分析--LocaleResolver(一)

概述

Spring MVC爲咱們提供國際化支持,經過設置系統的環境,根據運行環境使用不一樣的語言顯示。
Spring提供LocaleResolver接口的做用是解析客戶端使用的地區(Locale),目的是爲了根據這些信息實現視圖多語言即國際化。html

LocaleContextResolver接口繼承LocaleResolver接口,增長時區(TimeZone)支持。web

解析器(默認AcceptHeaderLocaleResolver)

AcceptHeaderLocaleResolver解析器implements LocaleResolver接口,重寫resolverLocale(HttpServletRequest request)方法,經過檢查客戶端發送請求中的Accept-Language頭來肯定客戶端Locale(地區信息)。spring

此解析器不支持程序設置Locale,只能經過改變客戶端Accept-Language頭信息來改變設置,核心源碼以下:chrome

/**
 * 從當前的request中解析Locale
 */
@Override
public Locale resolveLocale(HttpServletRequest request) {
    // 獲取默認設置,可在配置AcceptHeaderLocaleResolver Bean中設置defaultLocale屬性
    Locale defaultLocale = getDefaultLocale();
    // 設置了默認值而且請求中沒有Accept-Language頭信息時,使用默認設置
    if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
        return defaultLocale;
    }
    // 從當前請求中獲取Locale
    Locale requestLocale = request.getLocale();
    // 從配置中獲取支持的Locale集合,可在AcceptHeaderLocaleResolver Bean中設置supportedLocales屬性
    List<Locale> supportedLocales = getSupportedLocales();
    // 未設置supportedLocales或者supportedLocales中包括請求Locale,則使用請求Locale
    if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
        return requestLocale;
    }
    // 找到設置的Locale集合中是否有請求的Locale
    Locale supportedLocale = findSupportedLocale(request, supportedLocales);
    if (supportedLocale != null) {
        return supportedLocale;
    }
    return (defaultLocale != null ? defaultLocale : requestLocale);
}

/**
 * 不支持程序設置Locale
 */
@Override
public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
    throw new UnsupportedOperationException(
            "Cannot change HTTP accept header - use a different locale resolution strategy");
}

實戰

  • 項目結構

  • 配置文件

在Spring MVC配置文件中配置資源加載以及AcceptHeaderLocaleResolver Bean,配置以下:瀏覽器

<!-- 國際化資源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <!-- 若是資源文件放在classpath下,basename的value必須有classpath:前綴,不然報錯:No message found under code... -->
    <property name="basename" value="classpath:i18n/messages" />
    <!-- 若是在國際化資源文件中找不到對應代碼的信息,就用這個代碼做爲名稱返回  -->
    <property name="useCodeAsDefaultMessage" value="true" />
    <!--<property name="defaultEncoding" value="ISO-8859-1"/>-->
</bean>
<!-- LocaleResolver解析器 -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
    <property name="defaultLocale" value="zh_CN"/>
</bean>
  • 屬性文件

在類路徑下建立配置文件,本項目放置路徑爲:resources/i18n/messages_*.proerties,詳見項目結構,配置文件中配置信息以下:app

messages_en.propertieside

message.locale=en

messages_en _US.properties學習

message.locale=en_US

messages_zh _CN.properties測試

message.locale=zh_CN
  • 控制器

編寫Controller控制器,以便測試,代碼以下:spa

@GetMapping(value = "/acceptHeaderLocaleResolver" , produces = "text/html;charset=UTF-8")
@ResponseBody
public String test(HttpServletRequest request) {
    String clientLocale = "";
    Enumeration<Locale> enus =  request.getLocales();
    while (enus.hasMoreElements()){
        Locale locale = enus.nextElement();
        clientLocale += locale + ",";
    }
    RequestContext requestContext = new RequestContext(request);
    String value = requestContext.getMessage("message.locale");
    return "客戶端支持的Locale有:"+clientLocale+" </br>當前使用的Locale是:" + requestContext.getLocale() + " </br>使用的資源Locale文件是:" + value ;
}
  • 測試

以chrome爲例,首先確認chrome的語言設置,以下:

有上圖可見,測試的第一語言爲中文(簡體),咱們在地址欄訪問咱們的Controller,返回信息以下:

因爲客戶端設置的爲zh-CN,Spring MVC國際化使用的屬性文件是messages_zh _CN.properties,咱們經過修改客戶端屬性進行測試,調整chrome語言,即把英語設置到第一位,再次訪問Controller,返回信息以下:

此時的系統使用語言已經切換爲message_en.properties。

總結

  • 各瀏覽器默認的語言各不相同,可經過設置進行修改調整;
  • 客戶端請求頭Accept-Languages的第一個(權重最大)爲Spring MVC使用的Locale;
  • 權重最大的Locale名必須與屬性文件一致,不然找不到,如Accept-Languages的第一個爲en,則資源文件名必須設置爲messages_en.properties,若是第一個是zh-CN,則資源名稱爲messages_zh _CN.properties;
  • 使用messageSource Bean時,若是資源文件放在類路徑下,basename的值必須以classpath:開頭。

最後建立了qq羣方便你們交流,可掃描加入,同時也可加我qq:276420284,共同窗習、共同進步,謝謝!

相關文章
相關標籤/搜索