参考文章地址:
http://blog.sina.com.cn/s/blog_6d3c1ec601014eyj.html
http://www.mkyong.com/spring-mvc/spring-mvc-internationalization-example/
Spring国际化
在web开发中经常会遇到国际化的问题,那么在spring mvc中如何实现动态国际化。Spring使用ResourceBundleMessageSou
I18N
人们常把I18N作为“国际化”的简称,其来源是英文单词 internationalization的首末字符i和n。18为中间的字符数。
A、LocaleResolver(本地化解析器)
org.springframework.web.servlet.LocaleResolver
public interface LocaleResolver
DispatcherServlet允许使用客户端本地化信息自动解析消息。这个工作由实现LocaleResolver的对象来完成。
但收到请求时,DispatcherServlet查找LocaleResolver,若找到就是用它来设置Locale信息。
A.1、LocaleResolver的实现类
A.1.1、AcceptHeaderLocaleResolv
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolv
public class AcceptHeaderLocaleResolv
这个本地化解析器检查请求中客户端浏览器发送的accept-language头信息,这里包含客户端操作系统的本地化信息。
A.1.2、CookieLocaleResolver
org.springframework.web.servlet.i18n.CookieLocaleResolver
public class CookieLocaleResolver extends CookieGenerator implements LocaleResolver
这个本地化解析器检查客户端中的cookie是否包含本地化信息。若有就使用。
A.1.3、SessionLocaleResolver
org.springframework.web.servlet.i18n.SessionLocaleResolver
java.lang.Object
org.springframework.web.servlet.i18n.AbstractLocaleResolver
org.springframework.web.servlet.i18n.SessionLocaleResolver
public class SessionLocaleResolver extends AbstractLocaleResolver
这个本地化解析器检查客户端中的session是否包含本地化信息。若有就使用。
A.1.4、FixedLocaleResolver
org.springframework.web.servlet.i18n.FixedLocaleResolver
java.lang.Object
org.springframework.web.servlet.i18n.AbstractLocaleResolver
org.springframework.web.servlet.i18n.FixedLocaleResolver
public class FixedLocaleResolver extends AbstractLocaleResolver
这个本地化解析器返回一个固定的本地化信息。默认值为当前JVM的locale。
A.2、如何获得客户端的locale
通过RequestContext.getLocale()方法来获取由本地化解析器解析的客户端的本地化信息。
A.2.1、RequestContext
org.springframework.web.servlet.support.RequestContext
public class RequestContext extends Object
Context holder for request-specific state, like current web application context, current locale, current theme, and potential binding errors. Provides easy access to localized messages and Errors instances.
Request特殊状态的上下文持有者,如:当前web的application context,当前locale,当前主题和可能捆绑的错误。使访问本地化的信息和错误实例。
A.2.2、RequestContext取得locale的例子
public ModelAndView handleRequest(HttpServletRequest req,
RequestContext requestContext = new RequestContext(req);
Locale myLocale = requestContext.getLocale();
System.out.println(myLocale);
}
B、MessageSource
org.springframework.context.MessageSource
public interface MessageSource
spring通过实现MessageSource接口,来支持国际化。MessageSource来定义国际化需要资源的接口。MessageSource有很多实现方法,ResourceBundleMessageSou
B.1、ResourceBundleMessageSou
org.springframework.context.support.ResourceBundleMessageSou
public class ResourceBundleMessageSou
org.springframework.context.support.MessageSourceSupport
org.springframework.context.support.AbstractMessageSource
org.springframework.context.support.ResourceBundleMessageSou rce
MessageSource implementation that accesses resource bundles using specified basenames. This class relies on the underlying JDK's ResourceBundle implementation, in combination with the JDK's standard message parsing provided by MessageFormat.
它是MessageSource的一个实现,它访问资源束,资源束的路径由的basenames属性来指定。这个类依赖于JDK的底层类java.util.ResourceBundle。并结合由java.text.MessageFormat类提供的JDK标准message解析。
set方法
void
Set a single basename, following ResourceBundle conventions: essentially, a fully-qualified classpath location. If it doesn't contain a package qualifier (such as org.mypackage), it will be resolved from the classpath root.
Messages will normally be held in the "/lib" or "/classes" directory of a web application's WAR structure. They can also be held in jar files on the class path.
Note that ResourceBundle names are effectively classpath locations: As a consequence, the JDK's standard ResourceBundle treats dots as package separators. This means that "test.theme" is effectively equivalent to "test/theme", just like it is for programmatic java.util.ResourceBundle usage.
设置单个basename,遵照ResourceBundle协定:一个合格的classpath路径。若它没有包含包路径(如:org.mypackage),它将被解析classpath的根目录。
信息一般被放在WAR结构的web项目的/lib或/classes目录下。你也可以放在对应的jar文件中。
要注意的是:JDK中使用“.”作为路径的分隔符。也就是说“test.theme”实际表示为根目录下的“test/theme”目录。
B.1.1、ResourceBundleMessageSou
<!-- 资源文件绑定器 -->
<bean id="messageSource"class="org.springframework.context.support.ResourceBundleMessageSou
</bean>
其中,message-info是你的properties文件的通用名。如:我的配置文件叫messages.properties,messages_zh_CN.properties等等。
B.1.2、范例说明
范例1
1.配置messagesSource的bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
</beans>
关于basename的命名方式曾困扰我好久,特别是要加上包的名称,指定properties存放位置。一定要注意不然会报org.springframework.context.NoSuchMessageException的错
2.资源文件messages_zh_CN.properties
customer.name=david, age \: {0}, URL \: {1}
ABC=sdsd
3.测试类
package spring.chapter13.demo2;
import java.util.Locale;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplication
public class test {
}
因为ApplicationContext也是MessageSource接口的实现,故可以直接调用getMessage()方法。
C、HandlerInterceptor(处理拦截器接口)
org.springframework.web.servlet.HandlerInterceptor
public interface HandlerInterceptor
C.1、LocaleChangeInterceptor(处理拦截器实现)
org.springframework.web.servlet.i18n.LocaleChangeInterceptor
java.lang.Object
org.springframework.web.servlet.handler.HandlerInterceptorAdapte r
org.springframework.web.servlet.i18n.LocaleChangeInterceptor
public class LocaleChangeInterceptor extends HandlerInterceptorAdapte
前面LocaleResolver是自动解析用户的本地化信息locale,除了这个方法外,还可以把一个Interceptor拦截器放到处理器controller中,以便在某种情况下改变locale。(例如:基于请求中参数变更locale)。
C.1.1、基于拦截器的范例
我们再回到《[spring]8 初识MVC和Spring MVC框架》中的范例上,让我们在这个范例的基础上增加动态国际化支持,基于请求参数的动态国际。
范例2
1.Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
</beans>
我们定义了locale解析器(localeResolver)用于解析locale,还定义了一个处理拦截器(HandlerInterceptor)用于拦截url中locale参数。并在处理映射(handlerMapping)中增加了拦截器(Interceptor)。
2.自定义的locale解析器
package spring.chapter13.demo1;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolv
public class MyAcceptHeaderLocaleReso
}
若使用AcceptHeaderLocaleResolv
3.资源文件的定义
<?xml version="1.0" encoding="UTF-8"?>
<beans …>
</beans>
4.Controller处理器的处理方法
public ModelAndView handleRequest(HttpServletRequest req,
D、用Spring标签实现国际化
Spring标签中实现国际化的标签为spring:message。详细细节见《[spring]14 使用Spring标签库》。
范例3
1.在web.xml中加载spring配置文件
<!-- 使用监听器加载spring配置文件 -->
<context-param>
</context-param>
<listener>
</listener>
2.配置Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
</beans>
3.定义资源文件
customer.name=david china, age \: {0}, URL \: {1}
ABC=sdsdx
4.JSP文件中使用标签
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="from"%>
<html>
</html>
--------------------------------------------------------------------------------------------------------------------------------------------------
In Spring MVC application, comes with few “LocaleResolver” to support the internationalization or multiple languages features. In this tutorial, it shows a simple welcome page, display the message from properties file, and change the locale based on the selected language link.
1. Project Folder
Directory structure of this example.
2. Properties file
Two properties files to store English and Chinese messages.
welcome.properties
welcome.springmvc = Happy learning Spring MVC
welcome_zh_CN.properties
welcome.springmvc = \u5feb\u4e50\u5b66\u4e60 Spring MVC
For UTF-8 or non-English characters , you can encode it with native2ascii tool.
3. Controller
Controller class, nothing special here, all the locale stuff is configure in the Spring’s bean configuration file later.
package com.mkyong.common.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class WelcomeController extends AbstractController{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("WelcomePage");
return model;
}
}
4. Spring Configuration
To make Spring MVC application supports the internationalization, register two beans :
1. SessionLocaleResolver
Register a “SessionLocaleResolver” bean, named it exactly the same characters “localeResolver“. It resolves the locales by getting the predefined attribute from user’s session.
If you do not register any “localeResolver”, the default AcceptHeaderLocaleResolver will be used, which resolves the locale by checking the accept-language header in the HTTP request.
2. LocaleChangeInterceptor
Register a “LocaleChangeInterceptor” interceptor and reference it to any handler mapping that need to supports the multiple languages. The “paramName” is the parameter value that’s used to set the locale.
In this case,
- welcome.htm?language=en – Get the message from English properties file.
- welcome.htm?language=zh_CN – Get the message from Chinese properties file.
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="language" /> </bean> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" > <property name="interceptors"> <list> <ref bean="localeChangeInterceptor" /> </list> </property> </bean>
See full example below
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> <property name="defaultLocale" value="en" /> </bean> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="language" /> </bean> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" > <property name="interceptors"> <list> <ref bean="localeChangeInterceptor" /> </list> </property> </bean> <!-- Register the bean --> <bean class="com.mkyong.common.controller.WelcomeController" /> <!-- Register the welcome.properties --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="welcome" /> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
5. JSP
A JSP page, contains two hyperlinks to change the locale manually, and use the spring:message to display the message from the corresponds properties file by checking the current user’s locale.
WelcomePage.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<body>
<h1>Spring MVC internationalization example</h1>
Language : <a href="?language=en">English</a>|<a href="?language=zh_CN">Chinese</a>
<h3>
welcome.springmvc : <spring:message code="welcome.springmvc" text="default text" />
</h3>
Current Locale : ${pageContext.response.locale}
</body>
</html>
The ${pageContext.response.locale} can be used to display the current user’s locale.
Remember put the “<%@ page contentType=”text/html;charset=UTF-8″ %>” on top of the page, else the page may not able to display the UTF-8 (Chinese) characters properly.
7. Demo
Access it via http://localhost:8080/SpringMVC/welcome.htm, change the locale by clicking on the language’s link.
1. English locale – http://localhost:8080/SpringMVC/welcome.htm?language=en
2. Chinese locale – http://localhost:8080/SpringMVC/welcome.htm?language=zh_CN