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(一)的更多相关文章

  1. springMVC源码分析--国际化实现Session和Cookie(二)

    上一篇博客springMVC源码分析--国际化LocaleResolver(一)中我们介绍了springMVC提供的国际化的解决方案,接下来我们根据springMVC提供的解决方案来简单的实现一个多语 ...

  2. springMVC源码分析--HandlerInterceptor拦截器(一)

    对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器,HandlerInterceptor接口给我们提供了3个方法: (1)preHandle: 在执行controll ...

  3. springMVC源码分析--DispatcherServlet请求获取及处理

    在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...

  4. SpringMVC源码分析--容器初始化(五)DispatcherServlet

    上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...

  5. SpringMVC源码分析(3)DispatcherServlet的请求处理流程

    <springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...

  6. springMVC源码分析--视图View(一)

    之前的博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们已经介绍了数据返回值的处理,在博客springMVC源码分析--ViewResolver视图解析器( ...

  7. 8、SpringMVC源码分析(3):分析ModelAndView的形成过程

    首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...

  8. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  9. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

随机推荐

  1. 2015 多校联赛 ——HDU5386(暴力)

    Sample Input 1 3 5 2 2 1 2 3 3 2 1 3 3 3 3 3 3 3 3 3 3 H 2 3 L 2 2 H 3 3 H 1 3 L 2 3   Sample Output ...

  2. APIO 2016

    我好菜啊都不会 T1.boats 题目大意:给你N段区间,按顺序决定每段区间可以选一个数或不选,若选则选的这个数必须大于所有在这之前选的数,求有多少种方案.(N<=500,区间在[1,1e9]范 ...

  3. hihocoder #1142 : 三分·三分求极值

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的 ...

  4. Python之作业购物车

    作业之购物车优化 购物车优化要求如下: 用户入口: 启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够,够就 ...

  5. Redis Sentinel主从高可用方案

    Redis Sentinel主从高可用方案 本文介绍一种通过Jed和Sentinel实现Redis集群(主从)的高可用方案,该方案需要使用Jedis2.2.2及以上版本(强制),Redis2.8及以上 ...

  6. Unity使用C++作为游戏逻辑脚本的研究

    文章申明:本文来自JacksonDunstan的博客系列文章内容摘取和翻译,版权归其所有,附上原文的链接,大家可以有空阅读原文:C++ Scripting( in Unity) 一.C#和C++的通信 ...

  7. centos 7.X & centos6.X 防火墙基本命令

    Centos 7 firewall 命令:查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=public --add-port ...

  8. 毕业回馈-89c51之定时器/计数器(Timer/Count)

    今天分享的是89c51系列单片机的内部资源定时器/计数器,在所有的嵌入式系统中都包含这两个内部功能. 首先先了解几个定时器/计数器相关的概念: •时钟周期:时钟周期 T 是时序中最小的时间单位,具体计 ...

  9. 转:禁止360随身wifi驱动自动安装

    from:http://bbs.360safe.com/thread-2643500-1-1.html 有曾经数次卸载随身wifi后,插上又会自动安装随身wifi驱动的,也可以看看下面的解决办法. 卸 ...

  10. Http多线程版本

    上一篇文章讲了HTTP是如何通过TCP协议传输到服务器上,以及服务器接收到的报文信息请参考[HTTP与TCP的关系] 这篇文章主要讲述的多线程处理Http请求,关于多线程的好处我就不再叙述了.由于我们 ...