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来进一步介绍这几种实现方式。

  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7155550.html
Copyright © 2011-2022 走看看