Spring国际化
在web开发中经常会遇到国际化的问题,那么在spring mvc中如何实现动态国际化。Spring使用ResourceBundleMessageSource实现国际化资源的定义。使用LocaleResolver实现本地化信息的解析,使用LocaleChangeInterceptor实现本地化信息的监听(来实现url参数动态指定locale)。
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、AcceptHeaderLocaleResolver
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
public class AcceptHeaderLocaleResolver extends Object implements LocaleResolver
这个本地化解析器检查请求中客户端浏览器发送的accept-language头信息,这里包含客户端操作系统的本地化信息。
A.1.2、CookieLocaleResolver
org.springframework.web.servlet.i18n.CookieLocaleResolver
java.lang.Object org.springframework.web.util.CookieGenerator 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, HttpServletResponse res) throws Exception { 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有很多实现方法,ResourceBundleMessageSource是一个常用的实现。它按照ResourceBundle标准实施。
B.1、ResourceBundleMessageSource
org.springframework.context.support.ResourceBundleMessageSource
public class ResourceBundleMessageSource extends AbstractMessageSource implements BeanClassLoaderAware
org.springframework.context.support.MessageSourceSupport
org.springframework.context.support.AbstractMessageSource
org.springframework.context.support.ResourceBundleMessageSource
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 setBasename(String basename)
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、ResourceBundleMessageSource的配置
<!-- 资源文件绑定器 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages" /> <property name="useCodeAsDefaultMessage" value="true" /> </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" 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的名称必须定义为messageSource --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"> <value>spring.chapter13.demo2.messages</value> <!-- 前面的是包名,messages是配置文件的前缀 --> </property> </bean> </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.FileSystemXmlApplicationContext; public class test { public static void main(String[] args) { String fileName = "src/spring/chapter13/demo2/bean.xml"; ApplicationContext context = new FileSystemXmlApplicationContext(fileName); String name = ""; name = context.getMessage("ABC", null, Locale.CHINA); System.out.println(name); String namechinese = context.getMessage("customer.name", new Object[] { 28, "http://www.xxx.com" }, Locale.SIMPLIFIED_CHINESE); System.out.println("Customer name (Chinese) : " + namechinese); } }
因为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.HandlerInterceptorAdapter org.springframework.web.servlet.i18n.LocaleChangeInterceptor
public class LocaleChangeInterceptor extends HandlerInterceptorAdapter
前面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" 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"> <!-- 定义一个自定义的locale解析器 --> <bean id="localeResolver" class="spring.chapter13.demo1.MyAcceptHeaderLocaleResolver"> </bean> <!-- 定义一个locale的处理拦截器 --> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <!-- 定义处理映射HandlerMapping --> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors" ref="localeChangeInterceptor" /> <property name="mappings"> <props> <prop key="helloWorld.form*">helloWorldAction</prop> <!-- 把对helloWorld.form访问映射到id为helloWorldAction的bean上 --> </props> </property> </bean> <!-- 定义Controller --> <bean id="helloWorldAction" class="spring.chapter13.demo1.HelloWorldAction"> <property name="helloWorld"> <value>Hello Spring World!</value> </property> <property name="viewPage"> <value>sayHello.jsp</value> </property> </bean> </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.AcceptHeaderLocaleResolver; public class MyAcceptHeaderLocaleResolver extends AcceptHeaderLocaleResolver { private Locale myLocal; public Locale resolveLocale(HttpServletRequest request) { return myLocal; } public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { myLocal = locale; } }
若使用AcceptHeaderLocaleResolver类,程序运行会抛出异常"Cannot change HTTP accept header - use a different locale resolution strategy",根本原因是spring source做了限制,请注意上面的类,该类允许继承,所以需要改写setLocale方法。
3.资源文件的定义
<?xml version="1.0" encoding="UTF-8"?> <beans …> <!--bean的名称必须定义为messageSource --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"> <value>messages</value> <!-- 前面的是包名,messages是配置文件的前缀 --> </property> </bean> </beans>
4.Controller处理器的处理方法
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) throws Exception { RequestContext requestContext = new RequestContext(req); Locale myLocale = requestContext.getLocale(); String fileName = "../src/spring/chapter13/demo2/bean.xml"; ApplicationContext context = new FileSystemXmlApplicationContext( fileName); String name = ""; name = context.getMessage("ABC", null, myLocale); // 在该方法中处理用户请求 Map model = new HashMap(); model.put("helloWorld", getHelloWorld()); // 将helloWorld属性存 入model中 return new ModelAndView(getViewPage(), model); // 调用getViewPage获取要返回的页面 }
D、用Spring标签实现国际化
Spring标签中实现国际化的标签为spring:message。详细细节见《[spring]14 使用Spring标签库》。
范例3
1.在web.xml中加载spring配置文件
<!-- 使用监听器加载spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/bean.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
2.配置Spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <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的名称必须定义为messageSource --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"> <value>spring.chapter13.demo2.messages</value> <!-- 前面的是包名,messages是配置文件的前缀 --> </property> </bean> </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> <head> <title></title> </head> <body> <spring:message code="ABC"></spring:message> <from:form></from:form> </body> </html>
相关推荐
6. 浏览器请求的国际化实现:可以通过配置Accept-Language请求头,让浏览器自动选择用户偏好的语言。Spring MVC会根据用户浏览器发送的语言偏好,来决定使用哪个区域的资源文件。 具体实现时,可以创建多个后缀为....
Spring MVC 国际化实现详解 在 Spring MVC 框架中,实现国际化是一项非常重要的任务。国际化可以让我们的应用程序适应不同语言和地区,提高应用程序的可读性和可用性。本文将详细介绍如何使用 Spring MVC 实现国际...
接下来,我们将深入探讨Spring MVC中的国际化实现以及相关注解的使用。 1. **国际化基础** 国际化通常涉及到资源文件,这些文件存储了应用中的文本字符串,以不同的语言版本存在。在Spring MVC中,这些文件通常是....
在“spring mvc 3 国际化(下)——简单自定义操作”这一主题中,我们将深入探讨如何自定义国际化过程,以满足特定的应用场景需求。 首先,国际化的核心是资源文件,通常命名为`messages.properties`,用于存储默认...
Spring MVC的国际化实现原理分为两步: 1. 应用上下文(ApplicationContext)启动时,初始化`MessageSource`。`AbstractApplicationContext`在启动时调用`initMessageSource`方法,这会创建并配置`...
在Spring框架中,实现国际化(Internationalization,简称i18n)是常见的需求,它使得应用程序可以根据用户所在的地区提供不同的语言版本。以下是一个详细的步骤,解释如何在Spring应用中实现国际化。 1. **理解...
4. 国际化:支持多语言环境,通过MessageSource实现。 5. 文件上传下载:提供便捷的文件上传和下载功能。 五、配置详解 sprintMVC.xml文件是Spring3 MVC的配置文件,它包含了上述核心组件的配置。例如,定义...
包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。 当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。(例如: org.springframework.web....
在Spring MVC框架中,实现国际化是一项重要的功能,它允许应用程序为不同的地区和语言提供本地化的显示内容。本实例将向您展示如何轻松配置Spring MVC以支持国际化。首先,我们需要了解几个核心概念: 1. **资源...
在实际开发中,我们还会涉及单元测试、异常处理、国际化支持、安全控制等多个方面。Spring MVC提供了MockMvc工具来进行控制器的单元测试,而Spring Security则可以用来实现权限管理和认证。同时,我们可以使用拦截器...
这个简易版的 Spring MVC 框架可能没有包含所有的特性,如拦截器、国际化、上传下载等,但它足以帮助初学者理解 Spring MVC 的基本工作原理。在实际项目中,开发者可以根据需求逐步添加和配置更多功能,以构建更复杂...
【标题】"Spring MVC + Spring + Hibernate 全注解整合开发视频教程 09" 提供了一次深入了解Java企业级应用开发的机会,特别是在使用Spring MVC、Spring和Hibernate这三大核心框架进行全注解配置的场景下。...
10. **国际化和本地化**:通过消息源和LocaleResolver,Spring MVC可以轻松实现应用的多语言支持。 在实际开发中,我们可以通过Maven或Gradle等构建工具将Spring MVC 4.2.3依赖引入项目。同时,使用IDE如IntelliJ ...
10. **国际化支持**:通过消息源(MessageSource)和LocaleResolver,Spring MVC提供了强大的国际化支持,能够根据用户语言环境展示不同的内容。 11. **错误处理**:通过@ControllerAdvice和@ExceptionHandler,...
ApplicationContext 是 Spring 中的核心接口,它负责管理 Bean 的生命周期和依赖注入,同时提供事件发布和国际化等功能。 2. `org.springframework.beans-3.0.2.RELEASE.jar`:这个库包含 Bean 工厂(BeanFactory)...
本示例将详细介绍如何在Spring应用中实现国际化。 首先,我们需要了解国际化的基本概念。国际化是一个过程,通过这个过程,应用程序可以适应不同地区的文化、语言和习惯。这通常涉及到资源文件的使用,其中包含了...
Spring MVC还提供了强大的数据绑定、校验和国际化支持,极大地提高了开发效率。 其次,Spring框架是整个项目的中枢,它提供了一种依赖注入(DI)和面向切面编程(AOP)的机制,使得代码更加模块化,降低了组件之间...
- **本地化与国际化**:支持多种语言环境。 - **数据验证**:使用 Hibernate Validator 进行数据校验。 - **支持 AJAX**:与 jQuery、AngularJS 等库良好集成。 - **RESTful 支持**:易于构建 RESTful 风格的服务。 ...
"spring-mvc-showcase" 还涵盖了数据绑定、表单验证、国际化、异常处理等高级特性。例如,使用 @ModelAttribute 注解可以将请求参数自动绑定到 Controller 方法的参数上,而 @Valid 注解则可以实现数据验证。对于多...