WebApplicationContext 中特殊的 bean 型別(二)--- LocaleResolver

biubiubiubiubiubiubiu發表於2018-11-25

本章承接前面的內容,繼續講述 LocaleResolver。

LocalResolver 的作用是解析客戶的請求來自什麼地區,這樣就可以針對請求中的地區資訊,返回不同語言的檢視,以滿足 Spring MVC 工程國際化的需要。而 LocalContextResolver 則繼承自 LocalResolver 介面,加入了對時區的支援。

LocalResolver 原始碼

首先來看 LocalResolver 的預設配置(AcceptHeaderLocaleResolver)的原始碼,該配置實現了 LocalResolver 的介面,並且重寫 resolveLocale 方法,使其可以通過 Request 的 Header 欄位解析請求的地區資訊:

public class AcceptHeaderLocaleResolver implements LocaleResolver {
    public AcceptHeaderLocaleResolver() {
    }

    public Locale resolveLocale(HttpServletRequest request) {
        return request.getLocale();
    }

    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        throw new UnsupportedOperationException("Cannot change HTTP accept header - use a different locale resolution strategy");
    }
}
複製程式碼

可以看到,這裡 resolveLocale 方法直接去拿了請求中的 locale 欄位,檢視客戶端這邊最支援哪種語言。並且該類不支援 set 方法。

LocalResolver 程式碼例項

locale 專屬的 properties 檔案

首先,我們需要配置三個對應語言的 resource 檔案,在 resources/locales 資料夾下分別建立 locale_en.properties, locale_en_US.properties, locale_zh_CN.properties 檔案,注意直接建立這三個檔案後 Intellij 會把它合到一個資料夾裡面(這裡應該會變成一個名為 locale 資料夾)。properties 檔案內的程式碼分別是:

# locale_en.properties 檔案
message.locale=en_hello
複製程式碼
# locale_en_US.properties 檔案
message.locale=en_US_hello
複製程式碼
# locale_zh_CN.properties 檔案
message.locale=zh_CN_hello
複製程式碼

LocaleResolver 在 Spring 配置檔案中的配置

在 root-context 配置 LocalResolver 的 bean,並且配置對應的國際化資原始檔 ReloadableResourceBundleMessageSource,其中的方法可以針對輸入的 Locale 物件去獲取對應的 resource 檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <context:component-scan base-package="com.test.myapp.example"/>

	<!-- 其餘 bean 配置 -->

    <!--LocaleResolver 配置-->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
    </bean>

    <!-- 國際化資原始檔 -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!-- 如果資原始檔放在classpath下,basename的value必須有classpath:字首,否則報錯:No message found under code... -->
    	<!-- 這個地方 value 是紅色也沒問題,Spring MVC 在執行的時候還是會找到這些資原始檔 -->
        <property name="basename" value="classpath:locales/locale" />
        <!-- 如果在國際化資原始檔中找不到對應程式碼的資訊,就用這個程式碼作為名稱返回  -->
        <!--<property name="useCodeAsDefaultMessage" value="true" />-->
        <!--<property name="defaultEncoding" value="ISO-8859-1"/>-->
    </bean>

	<!-- 其餘 bean 配置 -->

</beans>
複製程式碼

LocaleResolver 測試介面

然後就是為我們的 LocaleResolver 配置一個介面,該介面的功能是獲取發出當前的客戶端支援哪些語言,並且最為偏好的語言是什麼,之後再去獲取對應的 properties 檔案中的資訊。

@Controller
public class LocaleResolverController {
    @RequestMapping(value="/accept-header-resolver.do", method = RequestMethod.GET)
    public ModelAndView resolveLocale(HttpServletRequest request) {
        String clientLocale = "";
        // 獲取客戶端支援的語言
        Enumeration<Locale> locales = request.getLocales();
        while (locales.hasMoreElements()) {
            Locale locale = locales.nextElement();
            clientLocale += locale + ",";
        }
        RequestContext requestContext = new RequestContext(request);
        // 獲取對應地區的 properties 中的資訊
        String value = requestContext.getMessage("message.locale");

        ModelAndView modelAndView = new ModelAndView("localeResolver");

        modelAndView.addObject("clientLocale", clientLocale);
        modelAndView.addObject("currentLocale", requestContext.getLocale());
        modelAndView.addObject("localeResource", value);
        return modelAndView;
    }
}
複製程式碼

上述程式碼中 clientLocale 表示客戶端瀏覽器支援的語言,currentLocale 則是客戶端的偏好語言,value 則表示根據客戶端偏好語言取回的對應語言 properties 中的欄位值。

LocaleResolver 測試前端頁面

上面測試介面返回的是一個 ModelAndView 物件,因此,我們還需要 jsp 前端檔案,來輸出上述的欄位:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>locale resolver page</title>
</head>
<body>
<p>
    客戶端支援:${clientLocale} 客戶端當前地區:${currentLocale}, 服務端對應內容:${localeResource}
</p>
</body>
</html>
複製程式碼

我們已經完成了具體程式碼的編寫,下面進入測試。

測試

這次測試以 chrome 為例,首先檢視 chrome 設定部分:

![chrome 語言設定](/Users/shenruofan/Desktop/螢幕快照 2018-11-06 下午4.32.43.png)

可以看到,語言設定這一欄我們把偏好語言設為英語(EN)。執行工程後,在瀏覽器中輸入:http://localhost:8080/accept-header-resolver.do,我們會看到如下的標識:

客戶端支援:en,zh,en_US,zh_CN, 客戶端當前地區:en, 服務端對應內容:en_hello
複製程式碼

之後,我們在語言設定中把中文(簡體)(zh_CN)放在語言偏好的第一位,再輸入相同的地址,則會出現如下的標識:

客戶端支援:zh_CN,zh,en,en_US, 客戶端當前地區:zh_CN, 服務端對應內容:zh_CN_hello
複製程式碼

這可以說明,我們的 LocaleResolver 在工程已經生效。

相關文章