一.简单国际化
1.1ResourceBundleMessageSource:配置文件中管理国际化资源文件
在之前学习SpringMVC自定义国际化错误消息的显示中,进行了简单国际化的学习。现在进行回顾,步骤如下:
1.写好国际化资源文件
login_en_US.properties:
welcomeInfo=welcome
username=USERNAME
password=PASSWORD
loginBtn=LOGIN
login_zh_CN.properties
welcomeInfo=\u6B22\u8FCE\u767B\u5F55
username=\u7528\u6237\u540D
password=\u5BC6\u7801
loginBtn=\u767B\u5F55
2.让Spring的ResourceBundleMessageSource管理国际化资源文件
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
<property name="basename" value="loginpage/login"></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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 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>
1.2 ResourceBundleMessageSource:程序中获得国际化信息
在之前的简单国家化的实验中,在配置文件中使用ResourceBundleMessageSource来管理国际化资源文件。现在可以在程序中使用ResourceBundleMessageSource类获得国际化信息。
@Controller
public class I18nController {
@Autowired
private ResourceBundleMessageSource messageSource;
@RequestMapping("/tologinpage")
public String toLoginpage(Locale locale){
System.out.println(locale);
String welcome=messageSource.getMessage("welcomeInfo", null, locale);
System.out.println(welcome);
return "login";
}
}
二. 国际化区域信息解析器
2.1 概述
默认情况下,SpringMVC根据Accept-Language参数判断客户端的本地化类型。当接收请求后,SpringMVC会在上下文中查找一个本地化解析器LocaleResolver,找到后使用它获取请求所对应的本地化类型信息。
SpringMVC中区域信息是由区域解析器得到的。
private LocaleResolver localeResolver;
默认会使用一个AcceptHeaderLocaleResolver。所有用到区域信息的地方,都是使用 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");
}
}
在render方法中,使用这个区域信息:
Locale locale = this.localeResolver.resolveLocale(request);
2.2 本地化解析器
- AcceptHeaderLocaleResolver:根据HTTP请求头的Accept-Language参数确定本地化类型,如果没有显示定义本地化解析器,SpringMVC将会使用该解析器。
- CookieLocaleResolver:根据指定的Cookie值确定本地haul类型。
- SessionLocaleResolver:从请求参数中获取本次请求对应的本地化类型。
- ...
AcceptHeaderLocaleResolver源码:知道了这个Locale是从请求中获得的。
@Override
public Locale resolveLocale(HttpServletRequest request) {
return request.getLocale();
}
可以自己看一下其他解析器的源码,查询这个解析器是从哪获得的。
三.通过超链接切换Locale
3.1 使用SessionLocaleResolver实现点击超链接切换国际化
1.页面链接
<!-- 如果点击超链接切换国际化 -->
<a href="tologinpage?locale=zh_CN">中文</a><a href="tologinpage?locale=en_US">English</a>
2.控制器方法
@RequestMapping("/tologinpage")
public String toLoginpage(@RequestParam(value="locale",defaultValue="zh_CN")String localeStr,Locale locale,Model model,HttpSession session){
Locale l=null;
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";
}
3.配置文件
<!-- 区域信息从session中拿 -->
<bean id="localeResovler" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
3.2 SessionLocale和LocaleInterceptor结合完成切换国际化
SpringMVC还允许装配一个动态更改本地化类型的拦截器,这样通过指定一个请求擦书就可以控制单个请求的本地化类型。
这个拦截器就是LocaleChangeInterceptor,可以从请求参数中获取本次请求对应的本地化类型。
工作原理:
配置:
<!-- 区域信息从session中拿 -->
<bean id="localeResovler" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<!-- 拦截器 -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
3.3 自定义国际化解析器
1.页面链接
<!-- 如果点击超链接切换国际化 -->
<a href="tologinpage?locale=zh_CN">中文</a><a href="tologinpage?locale=en_US">English</a>
2.自定义国际化解析器,继承了LocaleResolver类:
public class MyLocaleResolver implements LocaleResolver{
/*
* 解析返回Locale
* (non-Javadoc)
* @see org.springframework.web.servlet.LocaleResolver#resolveLocale(javax.servlet.http.HttpServletRequest)
*/
@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale locale=null;
String localeStr=request.getParameter("locale");
System.out.println(localeStr);
//如果带了Locale参数,就用参数指定的区域信息
//如果没带就使用请求头的区域信息
if(localeStr!=null && !"".equals(localeStr)){
locale=new Locale(localeStr.split("_")[0],localeStr.split("_")[1]);
}else{
locale=request.getLocale();
}
return null;
}
/*
* 修改Locale
* (non-Javadoc)
* @see org.springframework.web.servlet.LocaleResolver#setLocale(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.util.Locale)
*/
@Override
public void setLocale(HttpServletRequest request,
HttpServletResponse response, Locale locale) {
// TODO Auto-generated method stub
}
}
3.因为国际化解析器的初始化是在DispatcherServlet中按照id在IOC容器中寻找到的,所以进行配置。
<!-- 自定义区域信息解析器 -->
<!-- 因为在DispatchServlet中初始化区域信息解析器的时候,使用id在IOC容器中寻找-->
<bean id="localeResolver" class="com.test.controller.MyLocaleResolver"></bean>