文章目录

  • 一、SpringMVC国际化的步骤
  • 1.国际化文件
  • 2.SpringMVC管理国际化资源文件
  • 3.在页面取值
  • 二、国际化区域信息解析器
  • 三、在程序中获取国际化信息
  • 四、扩展:点击链接切换国际化
  • 方式1:自定义区域信息解析器
  • 方式2:使用SessionLocaleResolver实现国际化
  • 方式3:SessionLocaleResolver配合LocaleChangeInterceptor完成点击链接国际化



使用SpringMVC来做国际化只有三步:
①写好国际化文件。
②让SpringMVC的ResourceBundleMessageSource管理国际化资源文件。
③直接去页面取值。

一、SpringMVC国际化的步骤

1.国际化文件

仅以中英国际化为例,国际化文件的文件名如下:

  • i18n_zh_CN.properties 中文(简体)
  • i18n_en_US.properties 英语(美国)
  • i18n_en.properties 中文
  • i18n_zh.properties 英文

springmvc 国际化文件_国际化


创建哪种文件可以根据上图中浏览器的的语言环境。

2.SpringMVC管理国际化资源文件

  • 在SpringMVC中配置ResourceBundleMessageSource
  • value=“loginpage/i18n”:表示配置文件为loginpage文件夹下的i18n。
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basename" value="loginpage/i18n"></property>
	</bean>

3.在页面取值

  • 在显示页面使用fmt进行取值。
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>
		<fmt:message key="welcomeinfo"/>
	</h1>
	<form action="">
		<fmt:message key="username"/>:<input/><br/>
		<fmt:message key="password"/>:<input/><br/>
		<input type="submit" value="<fmt:message key="loginBtn"/>">
	</form>
</body>
</html>

二、国际化区域信息解析器

springmvc 国际化文件_ide_02


private LocaleResolver localeResolver;:SpringMVC中的区域信息是由这个区域信息解析器得到的,该解析器是SpringMVC九大组件之一。

所有用到区域信息的地方,都是用LocaleResolver默认装配的AcceptHeaderLocaleResolver来获取 。

(1) 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");
	}
	...
}

(2) FixedLocaleResolver:使用系统默认的区域信息

源码:
public class FixedLocaleResolver extends AbstractLocaleContextResolver {
	...
	@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");
	}
	...
}

(3) SessionLocaleResolver:区域信息是从Session中获取

源码:
public class SessionLocaleResolver extends AbstractLocaleContextResolver {
	...
	@Override
	public Locale resolveLocale(HttpServletRequest request) {
		Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);
		if (locale == null) {
			locale = determineDefaultLocale(request);
		}
		return locale;
	}
	...
}

(4)CookieLocaleResolver:区域信息是从Cookie中获取

public class CookieLocaleResolver extends CookieGenerator implements LocaleContextResolver {
	...
	@Override
	public Locale resolveLocale(HttpServletRequest request) {
		parseLocaleCookieIfNecessary(request);
		return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
	}
	...
}

三、在程序中获取国际化信息

  • 这样有什么用呢?之前在做JSR303校验时,如果不使用表单标签,而使用原生表单,可以增加Model参数,可以把国际化信息拿到后放入隐含模型中,再到页面中取出。
@Autowired
	private ResourceBundleMessageSource messageSource;

	@RequestMapping("/tologinPage")
	public String tologinpage(Locale locale) {
		System.out.println(locale);
		String message = messageSource.getMessage("welcomeinfo", null, locale);
		System.out.println(message);
		return "login";
	}

四、扩展:点击链接切换国际化

方式1:自定义区域信息解析器

处理器页面

@Autowired
	private ResourceBundleMessageSource messageSource;

	@RequestMapping("/tologinPage")
	public String tologinpage(Locale locale) {
		System.out.println(locale);
		String message = messageSource.getMessage("welcomeinfo", null, locale);
		System.out.println(message);
		return "login";
	}

自定义区域信息解析器

public class MyLocaleResolver implements LocaleResolver {

	// 解析区域信息
	@Override
	public Locale resolveLocale(HttpServletRequest req) {
		Locale l = null;
		String localeStr = req.getParameter("locale");
		// 如果带了locale参数,就用参数指定的信息,没带就用请求头的
		if (localeStr != null && !"".equals(localeStr)) {
			// 将字符串切分
			l = new Locale(localeStr.split("_")[0], localeStr.split("_")[1]);
		} else {
			l = req.getLocale();
		}
		return l;
	}

	// 设置区域信息
	@Override
	public void setLocale(HttpServletRequest arg0, HttpServletResponse arg1, Locale arg2) {
		// 该异常模仿AcceptHeaderLocaleResolver
		throw new UnsupportedOperationException(
				"Cannot change HTTP accept header - use a different locale resolution strategy");
	}

}

显示页面

<body>
	<h1>
		<fmt:message key="welcomeinfo"/>
	</h1>
	<form action="">
		<fmt:message key="username"/>:<input/><br/>
		<fmt:message key="password"/>:<input/><br/>
		<input type="submit" value="<fmt:message key="loginBtn"/>">
	</form>
	<a href="tologinPage?locale=zh_CN">中文</a>|<a href="tologinPage?locale=en_US">English</a>
</body>

显示页面如下,点击中/英文连接可以切换语言:

springmvc 国际化文件_SpringMVC_03


springmvc 国际化文件_国际化_04

方式2:使用SessionLocaleResolver实现国际化

  • 从请求参数中获得locale的值,如果没带就用中文。即拿到代表区域信息的参数字符串后,包装成一个Locale对象,放入Session中。
@Autowired
	private ResourceBundleMessageSource messageSource;

	@RequestMapping("/tologinPage")
	public String tologinpage(@RequestParam(value = "locale", defaultValue = "zh_CN") String localeStr, Locale locale,
			 HttpSession session) {
		System.out.println(locale);
		String message = messageSource.getMessage("welcomeinfo", null, locale);
		System.out.println(message);
		Locale l = null;
		// 如果带了locale参数,就用参数指定的信息,没带就用默认的
		if (localeStr != null && !"".equals(localeStr)) {
			// 将字符串切分
			l = new Locale(localeStr.split("_")[0], localeStr.split("_")[1]);
		} else {
			l = locale;
		}
		session.setAttribute(SessionLocaleResolver.class.getName() + ".LOCALE", l);
		return "login";
	}

配置Session区域信息解析器

  • 区域信息从Session中拿
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>

依然可以完成中英文切换

springmvc 国际化文件_ide_05


springmvc 国际化文件_ide_06

方式3:SessionLocaleResolver配合LocaleChangeInterceptor完成点击链接国际化

  • SpringMVC中配置LocaleChangeInterceptor和localeResolver。
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
	
	<mvc:interceptors>
		<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
	</mvc:interceptors>

处理器

  • 将处理器信息请求参数包装成Locale的事情交给LocaleChangeInterceptor去做。
@Autowired
	private ResourceBundleMessageSource messageSource;

	@RequestMapping("/tologinPage")
	public String tologinpage(String localeStr, Locale locale,
			Model model, HttpSession session) {
		System.out.println(locale);
		String message = messageSource.getMessage("welcomeinfo", null, locale);
		System.out.println(message);
		return "login";
	}

##SessionLocaleResolver&LocaleChangeInterceptor的工作原理

springmvc 国际化文件_国际化_07


LocaleChangeInterceptor拦截器帮我们完成的步骤:

①发请求时带了一个区域信息参数叫做locale,其中指定了新的区域信息。

②获得locale参数信息,将其解析为Locale对象.

③将Locale对象放入LocaleResolver中。

LocaleChangeInterceptor还帮我们把区域信息Locale设置为Session的属性(装入Session中)。

来到页面后,可以使用SessionLocaleResolver区域信息解析器获取区域信息(从Session中获取)。