本文转自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头部确定默认区域。
- <bean id="localeResolver" class="org.springframewrok.web.servlet
- .i18n.SessionLocaleResolver">
- <property name="defaultLocale" value="en"/>
- </bean>
如果会话属性不存在,可以为这个解析器设置defaultLocale属性。请注意,通过修改保存该区域的会话属性,这个区域
解析器可以改变用户的区域设置。
3.按Cookie解析区域
你也可以检验用户浏览器中的Cookie,用CookieLocaleResolver来解析区域。如果Cookie不存在,它会根据accept-language HTTP头部确定默认区域。
- <bean id="localeResolver" class="org.springframework.web.servlet
- .i18n.CookieLocaleResolver"/>
这个区域解析器所采用的Cookie可以通过cookieName和cookieMaxAge属性进行定制。cookieMaxAge属性表示这个Cookie应该持续多少秒,-1表示这个Cookie在浏览器关闭之后就失效。
- <bean id="localeResolver" class="org.springframework.web.servlet
- .i18n.CookieLocaleResolver">
- <property name="cookieName" value="language"/>
- <property name="cookieMaxAge" value="3600"/>
- <property name="defaultLocale" value="en"/>
- </bean>
如果用户浏览器中不存在该Cookie,你也可以为这个解析器设置defaultLocale属性。通过修改保存该区域的Cookie,这个区域解析器能够改变用户的区域。
4.FixedLocaleResolver
一直使用固定的Local, 改变Local 是不支持的 。
5.修改用户的区域
除了显式调用LocaleResolver.setLocale()来修改用户的区域之外,还可以将LocaleChangeInterceptor拦截器应用到处理程序映射中,它会发现当前HTTP请求中出现的特殊参数。其中的参数名称可以通过拦截器的paramName属性进行自定义。如果这种参数出现在当前请求中,拦截器就会根据参数值来改变用户的区域。
- <beans...>
- ...
- <bean id="localeChangeInterceptor"
- class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
- <property name="paramName" value="language"/>
- </bean>
- <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- <property name="interceptors">
- <list>
- ...
- <ref bean="localeChangeInterceptor"/>
- </list>
- </property>
- </bean>
- <bean class="org.springframework.web.servlet.mvc.support
- .ControllerClassNameHandlerMapping">
- <property name="interceptors">
- <list>
- ...
- <ref bean="localeChangeInterceptor"/>
- </list>
- </property>
- </bean>
- <beans>
LocaleChangeInterceptor只能为启用了它的那些处理程序映射侦测参数。因此,如果web应用程序上下文中配置了不止一个处理程序映射,就必须在所有处理程序映射中注册这个拦截器,以便能在任意URL中改变它们的区域设置。
现在,利用language参数,可以通过任意URL修改用户的区域。例如,下面两个URL分别将用户的区域语言改成了美式
英语和德语。
- http://localhost:8080/court/welcome.htm?language=en_US
- http://localhost:8080/court/welcome.htm?language=de
DispatchServlet 会在 processRequest(HttpServletRequest request, HttpServletResponse response) 方法中设置LocaleContext, 把LocalContext 和当前线程关联起来. 代码如下:
- LocaleContextHolder.setLocaleContext (buildLocaleContext(request), this. threadContextInheritable );
DispatchServlet 中buildLocalContext代码如下:
- protected LocaleContext buildLocaleContext( final HttpServletRequest request) {
- return new LocaleContext() {
- public Locale getLocale() {
- return localeResolver .resolveLocale(request);
- }
- @Override
- public String toString() {
- return getLocale().toString();
- }
- };
- }
这里的Local通过localResolver 解析得到, localResolver 即是从Spring 配置文件配置的localResolver, 默认是"AcceptHeaderLocaleResolver".
如果你想要在 controller 中得到当前请求的Local, 代码可以如下写:
- Locale locale = LocaleContextHolder.getLocale();
或者你可以用Spring 中的RequestContextUtils 类方法getLocal得到 request 中保存的localResolver, 并用localResolver 解析得到Local. 代码如下:
- public static Locale getLocale (HttpServletRequest request) {
- LocaleResolver localeResolver = getLocaleResolver (request);
- if (localeResolver != null ) {
- return localeResolver.resolveLocale(request);
- }
- else {
- return request.getLocale();
- }
- }
localResolver 会在DispatcherServlet的doService 方法中,将localResolver保存到request 属性中 代码如下:
- 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:其实没有任何具体实现,是通过浏览器头部的语言信息来进行多语言选择。
- public class AcceptHeaderLocaleResolver implements LocaleResolver {
- @Override
- public Locale resolveLocale(HttpServletRequest request) {
- return request.getLocale();
- }
- @Override
- public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
- throw new UnsupportedOperationException(
- "Cannot change HTTP accept header - use a different locale resolution strategy");
- }
- }
FixedLocaleResolver:设置固定的语言信息,这样整个系统的语言是一成不变的,用处不大。
- public class FixedLocaleResolver extends AbstractLocaleContextResolver {
- public FixedLocaleResolver() {
- setDefaultLocale(Locale.getDefault());
- }
- public FixedLocaleResolver(Locale locale) {
- setDefaultLocale(locale);
- }
- public FixedLocaleResolver(Locale locale, TimeZone timeZone) {
- setDefaultLocale(locale);
- setDefaultTimeZone(timeZone);
- }
- @Override
- public Locale resolveLocale(HttpServletRequest request) {
- Locale locale = getDefaultLocale();
- if (locale == null) {
- locale = Locale.getDefault();
- }
- return locale;
- }
- @Override
- public LocaleContext resolveLocaleContext(HttpServletRequest request) {
- return new TimeZoneAwareLocaleContext() {
- @Override
- public Locale getLocale() {
- return getDefaultLocale();
- }
- @Override
- public TimeZone getTimeZone() {
- return getDefaultTimeZone();
- }
- };
- }
- @Override
- public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
- throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");
- }
- }
CookieLocaleResolver:将语言信息设置到Cookie中,这样整个系统就可以获得语言信息
- public class CookieLocaleResolver extends CookieGenerator implements LocaleContextResolver {
- //多语言cookie名称
- public static final String LOCALE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";
- //多语言时区cookie名称
- public static final String TIME_ZONE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".TIME_ZONE";
- //默认的多语言cookie名称
- public static final String DEFAULT_COOKIE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";
- private Locale defaultLocale;
- private TimeZone defaultTimeZone;
- public CookieLocaleResolver() {
- setCookieName(DEFAULT_COOKIE_NAME);
- }
- public void setDefaultLocale(Locale defaultLocale) {
- this.defaultLocale = defaultLocale;
- }
- protected Locale getDefaultLocale() {
- return this.defaultLocale;
- }
- public void setDefaultTimeZone(TimeZone defaultTimeZone) {
- this.defaultTimeZone = defaultTimeZone;
- }
- protected TimeZone getDefaultTimeZone() {
- return this.defaultTimeZone;
- }
- @Override
- public Locale resolveLocale(HttpServletRequest request) {
- parseLocaleCookieIfNecessary(request);
- return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
- }
- @Override
- public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
- parseLocaleCookieIfNecessary(request);
- return new TimeZoneAwareLocaleContext() {
- @Override
- public Locale getLocale() {
- return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
- }
- @Override
- public TimeZone getTimeZone() {
- return (TimeZone) request.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME);
- }
- };
- }
- private void parseLocaleCookieIfNecessary(HttpServletRequest request) {
- if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {
- // Retrieve and parse cookie value.
- Cookie cookie = WebUtils.getCookie(request, getCookieName());
- Locale locale = null;
- TimeZone timeZone = null;
- if (cookie != null) {
- String value = cookie.getValue();
- String localePart = value;
- String timeZonePart = null;
- int spaceIndex = localePart.indexOf(' ');
- if (spaceIndex != -1) {
- localePart = value.substring(0, spaceIndex);
- timeZonePart = value.substring(spaceIndex + 1);
- }
- locale = (!"-".equals(localePart) ? StringUtils.parseLocaleString(localePart) : null);
- if (timeZonePart != null) {
- timeZone = StringUtils.parseTimeZoneString(timeZonePart);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale +
- "'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : ""));
- }
- }
- request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
- (locale != null ? locale: determineDefaultLocale(request)));
- request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
- (timeZone != null ? timeZone : determineDefaultTimeZone(request)));
- }
- }
- @Override
- public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
- setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
- }
- @Override
- public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
- Locale locale = null;
- TimeZone timeZone = null;
- if (localeContext != null) {
- locale = localeContext.getLocale();
- if (localeContext instanceof TimeZoneAwareLocaleContext) {
- timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
- }
- addCookie(response, (locale != null ? locale : "-") + (timeZone != null ? ' ' + timeZone.getID() : ""));
- }
- else {
- removeCookie(response);
- }
- request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
- (locale != null ? locale: determineDefaultLocale(request)));
- request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
- (timeZone != null ? timeZone : determineDefaultTimeZone(request)));
- }
- protected Locale determineDefaultLocale(HttpServletRequest request) {
- Locale defaultLocale = getDefaultLocale();
- if (defaultLocale == null) {
- defaultLocale = request.getLocale();
- }
- return defaultLocale;
- }
- protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
- return getDefaultTimeZone();
- }
- }
SessionLocaleResolver:与CookieLocaleResolver类似将语言信息放到Session中,这样整个系统就可以从Session中获得语言信息。
- public class SessionLocaleResolver extends AbstractLocaleContextResolver {
- //语言信息放到session中的名称
- public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE";
- public static final String TIME_ZONE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".TIME_ZONE";
- @Override
- public Locale resolveLocale(HttpServletRequest request) {
- Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);
- if (locale == null) {
- locale = determineDefaultLocale(request);
- }
- return locale;
- }
- @Override
- public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
- return new TimeZoneAwareLocaleContext() {
- @Override
- public Locale getLocale() {
- Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);
- if (locale == null) {
- locale = determineDefaultLocale(request);
- }
- return locale;
- }
- @Override
- public TimeZone getTimeZone() {
- TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME);
- if (timeZone == null) {
- timeZone = determineDefaultTimeZone(request);
- }
- return timeZone;
- }
- };
- }
- @Override
- public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
- Locale locale = null;
- TimeZone timeZone = null;
- if (localeContext != null) {
- locale = localeContext.getLocale();
- if (localeContext instanceof TimeZoneAwareLocaleContext) {
- timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
- }
- }
- WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);
- WebUtils.setSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME, timeZone);
- }
- protected Locale determineDefaultLocale(HttpServletRequest request) {
- Locale defaultLocale = getDefaultLocale();
- if (defaultLocale == null) {
- defaultLocale = request.getLocale();
- }
- return defaultLocale;
- }
- protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
- return getDefaultTimeZone();
- }
- }
通过源码我们可以了解到springMVC对多语言的支持就是设置Locale的语言信息来实现的,只不过是设置了通过cookie、session等方式设置而已,接下来我们会通过demo来进一步介绍这几种实现方式。