zoukankan      html  css  js  c++  java
  • Spring MVC之LocaleResolver(解析用户区域)

    本文转自http://blog.csdn.net/rj042/article/details/23354225 感谢作者

    为了让web应用程序支持国际化,必须识别每个用户的首选区域,并根据这个区域显示内容。

    spring MVC应用程序中,用户的区域是通过区域解析器来识别的,它必须实现LocaleResolver接口。Spring MVC提供了几个LocaleResolver实现,让你可以按照不同的条件来解析区域。除此之外,你还可以实现这个接口,创建自己的区域解析器。

    要定义一个区域解析器,只需在web应用程序上下文中注册一个LocaleResolver类型的Bean就可以了。你必须将区域解析器的Bean名称设置为localeResolver,这样DispatcherServlet才能自动侦测到它。请注意,每DispatcherServlet只能注册一个区域解析器。

    1.按HTTP请求头部解析区域

    Spring采用的默认区域解析器是AcceptHeaderLocaleResolver。它通过检验HTTP请求的accept-language头部来解析区域。这个头部是由用户的web浏览器根据底层操作系统的区域设置进行设定。请注意,这个区域解析器无法改变用户的区域,因为它无法修改用户操作系统的区域设置。

    2.按会话属性解析区域

    解析区域的另一种方法是通过SessionLocaleResolver。它通过检验用户会话中预置的属性来解析区域。如果该会话属性

    不存在,它会根据accept-language HTTP头部确定默认区域。

    Xml代码  收藏代码
    1. <bean id="localeResolver" class="org.springframewrok.web.servlet  
    2.     .i18n.SessionLocaleResolver">  
    3.     <property name="defaultLocale" value="en"/>  
    4. </bean>  

    如果会话属性不存在,可以为这个解析器设置defaultLocale属性。请注意,通过修改保存该区域的会话属性,这个区域

    解析器可以改变用户的区域设置。

    3.按Cookie解析区域

    你也可以检验用户浏览器中的Cookie,用CookieLocaleResolver来解析区域。如果Cookie不存在,它会根据accept-language HTTP头部确定默认区域。 

    Xml代码  收藏代码
    1. <bean id="localeResolver" class="org.springframework.web.servlet  
    2.     .i18n.CookieLocaleResolver"/>  

    这个区域解析器所采用的Cookie可以通过cookieName和cookieMaxAge属性进行定制。cookieMaxAge属性表示这个Cookie应该持续多少秒,-1表示这个Cookie在浏览器关闭之后就失效。 

    Xml代码  收藏代码
    1. <bean id="localeResolver" class="org.springframework.web.servlet  
    2.     .i18n.CookieLocaleResolver">  
    3.     <property name="cookieName" value="language"/>  
    4.     <property name="cookieMaxAge" value="3600"/>  
    5.     <property name="defaultLocale" value="en"/>  
    6. </bean>     

    如果用户浏览器中不存在该Cookie,你也可以为这个解析器设置defaultLocale属性。通过修改保存该区域的Cookie,这个区域解析器能够改变用户的区域。

    4.FixedLocaleResolver 

     一直使用固定的Local, 改变Local 是不支持的 。

    5.修改用户的区域

    除了显式调用LocaleResolver.setLocale()来修改用户的区域之外,还可以将LocaleChangeInterceptor拦截器应用到处理程序映射中,它会发现当前HTTP请求中出现的特殊参数。其中的参数名称可以通过拦截器的paramName属性进行自定义。如果这种参数出现在当前请求中,拦截器就会根据参数值来改变用户的区域。

    Xml代码  收藏代码
    1. <beans...>  
    2.     ...  
    3.     <bean id="localeChangeInterceptor"  
    4.         class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">  
    5.         <property name="paramName" value="language"/>  
    6.     </bean>  
    7.     <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
    8.         <property name="interceptors">  
    9.             <list>  
    10.                 ...  
    11.                 <ref bean="localeChangeInterceptor"/>  
    12.             </list>  
    13.         </property>  
    14.     </bean>  
    15.     <bean class="org.springframework.web.servlet.mvc.support  
    16.         .ControllerClassNameHandlerMapping">  
    17.         <property name="interceptors">  
    18.             <list>  
    19.                 ...  
    20.                 <ref bean="localeChangeInterceptor"/>  
    21.             </list>  
    22.         </property>  
    23.     </bean>  
    24. <beans>  

    LocaleChangeInterceptor只能为启用了它的那些处理程序映射侦测参数。因此,如果web应用程序上下文中配置了不止一个处理程序映射,就必须在所有处理程序映射中注册这个拦截器,以便能在任意URL中改变它们的区域设置。

    现在,利用language参数,可以通过任意URL修改用户的区域。例如,下面两个URL分别将用户的区域语言改成了美式

    英语和德语。 

    Java代码  收藏代码
    1. http://localhost:8080/court/welcome.htm?language=en_US  
    2. http://localhost:8080/court/welcome.htm?language=de  
     
    6.使用Spring MVC时,  controller如何得到请求的 Local

    DispatchServlet 会在 processRequest(HttpServletRequest request, HttpServletResponse response) 方法中设置LocaleContext, 把LocalContext 和当前线程关联起来. 代码如下:

    [java] view plain copy
     
    1. LocaleContextHolder.setLocaleContext (buildLocaleContext(request), this. threadContextInheritable );  

    DispatchServlet 中buildLocalContext代码如下:

    [java] view plain copy
     
    1. protected LocaleContext buildLocaleContext( final HttpServletRequest request) {  
    2.         return new LocaleContext() {  
    3.             public Locale getLocale() {  
    4.                 return localeResolver .resolveLocale(request);  
    5.             }  
    6.             @Override  
    7.             public String toString() {  
    8.                 return getLocale().toString();  
    9.             }  
    10.         };  
    11. }  

    这里的Local通过localResolver 解析得到,  localResolver 即是从Spring 配置文件配置的localResolver, 默认是"AcceptHeaderLocaleResolver".

    如果你想要在 controller 中得到当前请求的Local,  代码可以如下写:

    [java] view plain copy
     
    1. Locale locale = LocaleContextHolder.getLocale();  

    或者你可以用Spring 中的RequestContextUtils 类方法getLocal得到 request 中保存的localResolver, 并用localResolver 解析得到Local.   代码如下:

    [java] view plain copy
     
    1. public static Locale getLocale (HttpServletRequest request) {  
    2.         LocaleResolver localeResolver = getLocaleResolver (request);  
    3.         if (localeResolver != null ) {  
    4.             return localeResolver.resolveLocale(request);  
    5.         }  
    6.         else {  
    7.             return request.getLocale();  
    8.         }  
    9. }  

    localResolver 会在DispatcherServlet的doService 方法中,将localResolver保存到request 属性中 代码如下:

    [java] view plain copy
     
    1. request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);  

    下文转自 http://blog.csdn.net/qq924862077/article/details/52878507 感谢作者 

    springMVC源码分析--国际化LocaleResolver(一)

    springMVC给我们提供了国际化支持,简单来说就是设置整个系统的运行语言,然后根据系统的运行语言来展示对应语言的页面,一般我们称之为多语言。springMVC国际化机制就是可以设置整个系统的运行语言,其定义了一个国际化支持接口LocaleResolver,提供的默认实现类如下图。

    springMVC国际化提供了四个默认实现的类AcceptHeaderLocaleResolver,FixedLocaleResolver、CookieLocaleResolver和SessionLocaleResolver。接下来我们简单介绍一下这四个实现类的源码。

    AcceptHeaderLocaleResolver:其实没有任何具体实现,是通过浏览器头部的语言信息来进行多语言选择。

    [java] view plain copy
     
     print?
    1. public class AcceptHeaderLocaleResolver implements LocaleResolver {  
    2.   
    3.     @Override  
    4.     public Locale resolveLocale(HttpServletRequest request) {  
    5.         return request.getLocale();  
    6.     }  
    7.   
    8.     @Override  
    9.     public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {  
    10.         throw new UnsupportedOperationException(  
    11.                 "Cannot change HTTP accept header - use a different locale resolution strategy");  
    12.     }  
    13.   
    14. }  

    FixedLocaleResolver:设置固定的语言信息,这样整个系统的语言是一成不变的,用处不大。

    [java] view plain copy
     
     print?
    1. public class FixedLocaleResolver extends AbstractLocaleContextResolver {  
    2.     public FixedLocaleResolver() {  
    3.         setDefaultLocale(Locale.getDefault());  
    4.     }  
    5.     public FixedLocaleResolver(Locale locale) {  
    6.         setDefaultLocale(locale);  
    7.     }  
    8.     public FixedLocaleResolver(Locale locale, TimeZone timeZone) {  
    9.         setDefaultLocale(locale);  
    10.         setDefaultTimeZone(timeZone);  
    11.     }  
    12.     @Override  
    13.     public Locale resolveLocale(HttpServletRequest request) {  
    14.         Locale locale = getDefaultLocale();  
    15.         if (locale == null) {  
    16.             locale = Locale.getDefault();  
    17.         }  
    18.         return locale;  
    19.     }  
    20.     @Override  
    21.     public LocaleContext resolveLocaleContext(HttpServletRequest request) {  
    22.         return new TimeZoneAwareLocaleContext() {  
    23.             @Override  
    24.             public Locale getLocale() {  
    25.                 return getDefaultLocale();  
    26.             }  
    27.             @Override  
    28.             public TimeZone getTimeZone() {  
    29.                 return getDefaultTimeZone();  
    30.             }  
    31.         };  
    32.     }  
    33.   
    34.     @Override  
    35.     public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {  
    36.         throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");  
    37.     }  
    38.   
    39. }  

    CookieLocaleResolver:将语言信息设置到Cookie中,这样整个系统就可以获得语言信息

    [java] view plain copy
     
     print?
    1. public class CookieLocaleResolver extends CookieGenerator implements LocaleContextResolver {  
    2.   
    3.     //多语言cookie名称  
    4.     public static final String LOCALE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";  
    5.   
    6.     //多语言时区cookie名称  
    7.     public static final String TIME_ZONE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".TIME_ZONE";  
    8.   
    9.       
    10.     //默认的多语言cookie名称  
    11.     public static final String DEFAULT_COOKIE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";  
    12.   
    13.     private Locale defaultLocale;  
    14.   
    15.     private TimeZone defaultTimeZone;  
    16.   
    17.     public CookieLocaleResolver() {  
    18.         setCookieName(DEFAULT_COOKIE_NAME);  
    19.     }  
    20.     public void setDefaultLocale(Locale defaultLocale) {  
    21.         this.defaultLocale = defaultLocale;  
    22.     }  
    23.   
    24.     protected Locale getDefaultLocale() {  
    25.         return this.defaultLocale;  
    26.     }  
    27.   
    28.     public void setDefaultTimeZone(TimeZone defaultTimeZone) {  
    29.         this.defaultTimeZone = defaultTimeZone;  
    30.     }  
    31.   
    32.     protected TimeZone getDefaultTimeZone() {  
    33.         return this.defaultTimeZone;  
    34.     }  
    35.   
    36.   
    37.     @Override  
    38.     public Locale resolveLocale(HttpServletRequest request) {  
    39.         parseLocaleCookieIfNecessary(request);  
    40.         return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);  
    41.     }  
    42.   
    43.     @Override  
    44.     public LocaleContext resolveLocaleContext(final HttpServletRequest request) {  
    45.         parseLocaleCookieIfNecessary(request);  
    46.         return new TimeZoneAwareLocaleContext() {  
    47.             @Override  
    48.             public Locale getLocale() {  
    49.                 return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);  
    50.             }  
    51.             @Override  
    52.             public TimeZone getTimeZone() {  
    53.                 return (TimeZone) request.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME);  
    54.             }  
    55.         };  
    56.     }  
    57.     private void parseLocaleCookieIfNecessary(HttpServletRequest request) {  
    58.         if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {  
    59.             // Retrieve and parse cookie value.  
    60.             Cookie cookie = WebUtils.getCookie(request, getCookieName());  
    61.             Locale locale = null;  
    62.             TimeZone timeZone = null;  
    63.             if (cookie != null) {  
    64.                 String value = cookie.getValue();  
    65.                 String localePart = value;  
    66.                 String timeZonePart = null;  
    67.                 int spaceIndex = localePart.indexOf(' ');  
    68.                 if (spaceIndex != -1) {  
    69.                     localePart = value.substring(0, spaceIndex);  
    70.                     timeZonePart = value.substring(spaceIndex + 1);  
    71.                 }  
    72.                 locale = (!"-".equals(localePart) ? StringUtils.parseLocaleString(localePart) : null);  
    73.                 if (timeZonePart != null) {  
    74.                     timeZone = StringUtils.parseTimeZoneString(timeZonePart);  
    75.                 }  
    76.                 if (logger.isDebugEnabled()) {  
    77.                     logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale +  
    78.                             "'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : ""));  
    79.                 }  
    80.             }  
    81.             request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,  
    82.                     (locale != null ? locale: determineDefaultLocale(request)));  
    83.             request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,  
    84.                     (timeZone != null ? timeZone : determineDefaultTimeZone(request)));  
    85.         }  
    86.     }  
    87.   
    88.     @Override  
    89.     public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {  
    90.         setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));  
    91.     }  
    92.   
    93.     @Override  
    94.     public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {  
    95.         Locale locale = null;  
    96.         TimeZone timeZone = null;  
    97.         if (localeContext != null) {  
    98.             locale = localeContext.getLocale();  
    99.             if (localeContext instanceof TimeZoneAwareLocaleContext) {  
    100.                 timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();  
    101.             }  
    102.             addCookie(response, (locale != null ? locale : "-") + (timeZone != null ? ' ' + timeZone.getID() : ""));  
    103.         }  
    104.         else {  
    105.             removeCookie(response);  
    106.         }  
    107.         request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,  
    108.                 (locale != null ? locale: determineDefaultLocale(request)));  
    109.         request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,  
    110.                 (timeZone != null ? timeZone : determineDefaultTimeZone(request)));  
    111.     }  
    112.   
    113.     protected Locale determineDefaultLocale(HttpServletRequest request) {  
    114.         Locale defaultLocale = getDefaultLocale();  
    115.         if (defaultLocale == null) {  
    116.             defaultLocale = request.getLocale();  
    117.         }  
    118.         return defaultLocale;  
    119.     }  
    120.   
    121.     protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {  
    122.         return getDefaultTimeZone();  
    123.     }  
    124.   
    125. }  

    SessionLocaleResolver:与CookieLocaleResolver类似将语言信息放到Session中,这样整个系统就可以从Session中获得语言信息。

    [java] view plain copy
     
     print?
    1. public class SessionLocaleResolver extends AbstractLocaleContextResolver {  
    2.   
    3.     //语言信息放到session中的名称  
    4.     public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE";  
    5.   
    6.     public static final String TIME_ZONE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".TIME_ZONE";  
    7.   
    8.   
    9.     @Override  
    10.     public Locale resolveLocale(HttpServletRequest request) {  
    11.         Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);  
    12.         if (locale == null) {  
    13.             locale = determineDefaultLocale(request);  
    14.         }  
    15.         return locale;  
    16.     }  
    17.   
    18.     @Override  
    19.     public LocaleContext resolveLocaleContext(final HttpServletRequest request) {  
    20.         return new TimeZoneAwareLocaleContext() {  
    21.             @Override  
    22.             public Locale getLocale() {  
    23.                 Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);  
    24.                 if (locale == null) {  
    25.                     locale = determineDefaultLocale(request);  
    26.                 }  
    27.                 return locale;  
    28.             }  
    29.             @Override  
    30.             public TimeZone getTimeZone() {  
    31.                 TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME);  
    32.                 if (timeZone == null) {  
    33.                     timeZone = determineDefaultTimeZone(request);  
    34.                 }  
    35.                 return timeZone;  
    36.             }  
    37.         };  
    38.     }  
    39.   
    40.     @Override  
    41.     public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {  
    42.         Locale locale = null;  
    43.         TimeZone timeZone = null;  
    44.         if (localeContext != null) {  
    45.             locale = localeContext.getLocale();  
    46.             if (localeContext instanceof TimeZoneAwareLocaleContext) {  
    47.                 timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();  
    48.             }  
    49.         }  
    50.         WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);  
    51.         WebUtils.setSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME, timeZone);  
    52.     }  
    53.   
    54.     protected Locale determineDefaultLocale(HttpServletRequest request) {  
    55.         Locale defaultLocale = getDefaultLocale();  
    56.         if (defaultLocale == null) {  
    57.             defaultLocale = request.getLocale();  
    58.         }  
    59.         return defaultLocale;  
    60.     }  
    61.   
    62.     protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {  
    63.         return getDefaultTimeZone();  
    64.     }  
    65.   
    66. }  


    通过源码我们可以了解到springMVC对多语言的支持就是设置Locale的语言信息来实现的,只不过是设置了通过cookie、session等方式设置而已,接下来我们会通过demo来进一步介绍这几种实现方式。

  • 相关阅读:
    dir for RequestHandler and request
    python globals和locals
    Spring AOP(通知、连接点、切点、切面)
    Elasticsearch和Head插件安装(转)
    服务发现
    全面的软件测试( 转)
    软件开发项目人员配置
    阿里云oss缩略图如何产生读取 超简单 不看后悔(转)
    Elasticsearch模糊查询
    小米Pro 安装苹果系统
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7155550.html
Copyright © 2011-2022 走看看