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来进一步介绍这几种实现方式。
springMVC源码分析--国际化LocaleResolver(一)的更多相关文章
- springMVC源码分析--国际化实现Session和Cookie(二)
上一篇博客springMVC源码分析--国际化LocaleResolver(一)中我们介绍了springMVC提供的国际化的解决方案,接下来我们根据springMVC提供的解决方案来简单的实现一个多语 ...
- springMVC源码分析--HandlerInterceptor拦截器(一)
对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器,HandlerInterceptor接口给我们提供了3个方法: (1)preHandle: 在执行controll ...
- springMVC源码分析--DispatcherServlet请求获取及处理
在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...
- SpringMVC源码分析(3)DispatcherServlet的请求处理流程
<springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...
- springMVC源码分析--视图View(一)
之前的博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们已经介绍了数据返回值的处理,在博客springMVC源码分析--ViewResolver视图解析器( ...
- 8、SpringMVC源码分析(3):分析ModelAndView的形成过程
首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...
- 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解
从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...
- springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)
之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...
随机推荐
- 【UVA–11997 K Smallest Sums 】
·哦,这题要用优先队列?那大米饼就扔一个手写堆上去吧! ·英文题,述大意: 输入n个长度为n的序列(题中是k,2<=k<=750).一种结果定义为:从每个序列中都要挑选一个数加 ...
- 例10-12 *uva1637(概率dp)
题意:36张扑克,平分成9摞,两张数字一样的可以拿走,每次随机拿两张,问能拿光的概率. 思路: 直接用搜索,表示出每摞剩余的牌数,然后利用全概率公式即可(P(A) = p(A|b1)*p(b1)+.. ...
- bzoj3831 [Poi2014]Little Bird 单调队列优化dp
3831: [Poi2014]Little Bird Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 505 Solved: 322[Submit][ ...
- 从Openvswitch代码看网络包的旅程
我们知道,Openvwitch可以创建虚拟交换机,而网络包可以通过虚拟交换机进行转发,并通过流表进行处理,具体的过程如何呢? 一.内核模块Openvswitch.ko的加载 OVS是内核态和用户态配合 ...
- 详解Tomcat配置JVM参数步骤
这里向大家描述一下如何使用Tomcat配置JVM参数,Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.您可以选择自己的需要选择不同的操作系统和对应的JDK ...
- Bootstrap3 栅格系统-实例:多余的列(column)将另起一行排列
如果在一个 .row 内包含的列(column)大于12个,包含多余列(column)的元素将作为一个整体单元被另起一行排列. <div class="row"> &l ...
- ZooKeeper之(一)ZooKeeper是什么
1.1 产生背景 当今是个分布式.集群.云计算等名词满天飞的时代.造成这种局面的一个重要因素就是,单一机器的处理能力已经不能满足我们的需求,不得不采用由多台机器组成的服务集群.服务集群对外提供服务的过 ...
- 十大豪门推送sdk,哪个更适合你
转自:http://jingyan.baidu.com/article/d621e8da0fd7042865913ff5.html 推送,使得开发者可以即时地向其应用程序的用户推送通知或者消息,与用户 ...
- rbac 概念
1 权限管理 1.1 什么是权限管理 分享牛原创,分享牛系列.基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户 ...
- Android 多窗口详解
多窗口支持 Android N 添加了对同时显示多个应用窗口的支持. 在手持设备上,两个应用可以在"分屏"模式中左右并排或上下并排显示. 在电视设备上,应用可以使用"画中 ...