spring 国际化的原理

spring core国际化

spring core支持国际化,是其它模块支持国际化的基础,正因为spring core支持国际化,spring mvc才能支持国际化。国际化就是MessageSource接口来实现的。MessageSource是个策略接口,提供了两个开箱即用的实现,ResourceBundleMessageSource和ReloadableResourceBundleMessageSource。ReloadableResourceBundleMessageSource顾名思义,不需要重启JVM就可以重新加载资源文件。

MessageSource

要想理解国际化,只要理解了MessageSource的getMessage方法

String getMessage(String code, Object[] args, Locale locale)

ResourceBundle就是资源文件,比如mylocale_zh_CN.properties、mylocale_zh_TW.properties,注意文件的后缀zh_CN、zh_TW代表地区语言。

mylocale_zh_CN.properties
my.code=爱你
mylocale_zh_TW.properties
my.code=愛你

getMessage(“my.code”,null,地区),如果地区是中国大陆,则返回爱你,如果是中国台湾则是愛你

spring启动对MessageSource的操作

spring启动时,applicationcontext会寻找MessageSource的bean,如果找到则使用,否则创建DelegatingMessageSource。
所以实现国际化,通常在beans.xml中配置

<!-- 国际化资源文件 -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basename" value="classpath:mylocale" />
		<property name="defaultEncoding" value="utf8" />
		<property name="useCodeAsDefaultMessage" value="true" />
	</bean>

上边的配置会将mylocale文件,当作消息源,getMessage时会从mylocale文件_地区语言取值,以下都是消息源

mylocale_zh_CN.properties
mylocale_zh_TW.properties
mylocale_en_US.properties

spring mvc国际化

到了web项目中,国际化通常有两个需求,第一,切换语言,比如菜单栏中有中英文按钮来切换当前语言。spring提供了LocaleChangeInterceptor
第二,切换后,要记住当前语言,在当前会话中始终维持所选语言,这就要用到session,所以spring提供了SessionLocaleResolver,除了SessionLocaleResolver还有两个locale相关类,CookieLocaleResolver、AcceptHeaderLocaleResolver

  • AcceptHeaderLocaleResolver,顾名思义,分别是通过header中的accept-language来识别locale
  • CookieLocaleResolver就是cookie中存储locale信息,比如cookie中存放locale、timezone等信息,跟SessionLocaleResolver正好相反,CookieLocaleResolver是将locale放在cookie中,而SessionLocaleResolver是将这些信息放在session中。

中英文切换LocaleChangeInterceptor

在这里插入图片描述
从类层次结构图中可以看出来,LocaleChangeInterceptor说到底是个拦截器,从源码得知在请求到达RequestMapping之前执行,它的作用,简单来说就是从请求中获取请求参数(默认是locale),然后在LocaleResolver设置当前locale。

@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws ServletException {

		String newLocale = request.getParameter(getParamName());
		if (newLocale != null) {
			if (checkHttpMethod(request.getMethod())) {
				LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
				if (localeResolver == null) {
					throw new IllegalStateException(
							"No LocaleResolver found: not in a DispatcherServlet request?");
				}
				try {
					localeResolver.setLocale(request, response, StringUtils.parseLocaleString(newLocale));
				}
				catch (IllegalArgumentException ex) {
					if (isIgnoreInvalidLocale()) {
						logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
					}
					else {
						throw ex;
					}
				}
			}
		}
		// Proceed in any case.
		return true;
	}

一般都会在spring-mvc中配置

<mvc:interceptor>
			<mvc:mapping path="/**" />
			<bean id="localeChangeInterceptor" class="com.bsmartd.handler.LocaleInterceptor"/>
		</mvc:interceptor>

SessionLocaleResolver 获取当前session中的地区

在这里插入图片描述

从类继承层次结构图上看,SessionLocaleResolver 是个解析器。
顶级接口类LocaleResolver的resolveLocale方法用来解析给定请求的locale。我们看到render时,会调用此方法。所以它的执行时机与LocaleChangeInterceptor是不同的。

	/**
	 * Resolve the current locale via the given request. Can return a default locale as
	 * fallback in any case.
	 * @param request the request to resolve the locale for
	 * @return the current locale (never {@code null})
	 */
	Locale resolveLocale(HttpServletRequest request);

DispatcherServlet

/**
	 * Render the given ModelAndView.
	 * <p>This is the last stage in handling a request. It may involve resolving the view by name.
	 * @param mv the ModelAndView to render
	 * @param request current HTTP servlet request
	 * @param response current HTTP servlet response
	 * @throws ServletException if view is missing or cannot be resolved
	 * @throws Exception if there's a problem rendering the view
	 */
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale = this.localeResolver.resolveLocale(request);
		response.setLocale(locale);
		//省略不相关的代码
		}

参考

mvc-localeresolver

发布了336 篇原创文章 · 获赞 369 · 访问量 193万+

猜你喜欢

转载自blog.csdn.net/wangjun5159/article/details/96293329