程序中的国际化问题也是一个非常重要的部分,好多的软件都支持国际化,不同的版本对应不同的语言。在进行国际化时,依照程序开发习惯,我们一般选择在页面层或者控制层做国际化处理,业务层和DAO层不要去国际化,在业务层或者DAo层只需设定国际化的key值即可,当然,key值尽量具有意义。
目前,spring提供了好多国际化的方式,例如AcceptHeaderLocaleResolver,session及cookie的国际化,这里仅介绍最实用,最普遍,笔者认为最实用最合理的国际化。
1、标签国际化
标签国际化我们可以用jstl的fmt方式进行国际化,也可以采用spring自己提供的标签<spring:message/>进行国际化。但尽量还是采用jstl的fmt方式,因为spring自带的标签在找不到国际化值时,整个系统会抛异常,完全不能运行,这也是spring标签的鸡肋。
首先,我们定义国际化文件,如下图结构,我们建立如下的工程结构
本人所用的操作系统为英文版本,所以默认的为en_US
在messages文件夹下,我们建立了2个国际化properties文件,分别为messages_en_US.properties和errors_en_US.properties.
在每个配置文件中我们定义相应的内容如下:messages_en_US.properties
message.springtagTest = this is spring tag international Test in messages.propertiesmessage.fmttagTest = this is fmt tag international Test in messages.properties
message.codeTest = this is code international Test,first paramenter is {0} in messages.properties
errors_en_US.properties
errors.springtagTest = this is spring tag international Test in errors.properties
errors.fmttagTest = this is fmt tag international Test in errors.properties
errors.codeTest = this is code international Test,first paramenter is {0} in errors.properties
如果是中文,需要采用zh_CN.bat 将中文转换为uncode编码的方式zh_CN.bat 的内容如下:
native2ascii -encoding utf-8 messages_zh_CN.txt > messages_zh_CN.properties
当然你也可以下载eclipse的properties插件,可以直接方便进行编辑。
2.国际化applicationContext文件的配置如下: 名字applicationContext-internationalization.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<description>国际化语言配置</description>
<!--**********************国际化支持信息配置*************************************************-->
<!-- Bean id 必须是“messageSource”,因为Spring 在装配系统Bean 时会根据这个名字进行查找-->
<!--
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages.messages"/>
</bean>
-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages.errors</value>
<value>messages.messages</value>
</list>
</property>
</bean>
<bean id="messageSourceHelper" class="com.jason.util.MessageSourceHelper">
<property name="messageSource">
<ref local="messageSource"/>
</property>
</bean>
</beans>
这里简单介绍下:
如果用户只有一个properties文件可采用如下配置
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages.messages"/>
</bean>
value的值表示在messages文件下有个messages文件,如果多个文件可采用如下的配置:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages.errors</value>
<value>messages.messages</value>
</list>
</property>
</bean>
代表在messages文件夹下存在2个文件,error 和messages 文件,至于取啥文件要根据客户端语言进行读取。
3、在页面我们引入jstl和spring的标签,
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
在页面中进行如下的调用就行了,该调用包含了带参数和不带参数的信息,当采用ftml时有多个问题,可采用bundle属性指定具体文件。
<div>
messages.properties: <font color="red"><spring:message code="message.springtagTest"/></font>
</div>
<div>
messages.properties: <font color="red"><fmt:message key="message.fmttagTest"/></font>
</div>
<div>
messages.properties: <fmt:message key="message.codeTest"><fmt:param value="paraments test"/></fmt:message>
</div>
<div>
2、java代码国际化
仅仅采用标签国际化,有时候难免会不够用,这个时候需要在controller层进行代码的控制。在controller层进行代码控制时,我们需要设置一个国际化的工具类,代码如下:
package com.jason.util;
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ResourceBundleMessageSource;
/**
* @author jgao
*
* 国际化信息工具类
*/
public class MessageSourceHelper {
private static MessageSource messageSource;
public void setMessageSource(ResourceBundleMessageSource messageSource) {
MessageSourceHelper.messageSource = messageSource;
}
public static String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
String msg = messageSource.getMessage(code, args, defaultMessage, locale);
return msg != null ? msg.trim() : defaultMessage;
}
}
如何给静态类经行实例化呢?其实很简单,只需要将其set方法取得static即可,在xml中做如下的配置,在上面的整体配置文件中,我们已经做了详细的描述。
<bean id="messageSourceHelper" class="com.jason.util.MessageSourceHelper"> <property name="messageSource">
<ref local="messageSource"/>
</property>
</bean>
配置完国际过文件,再配置application-servlet.xml,如下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置静态资源,直接映射到对应的文件夹,不被DispatcherServlet处理 -->
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/common/**" location="/common/"/>
<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />
<!--扫描web包,应用Spring的注解-->
<context:component-scan base-package="com.jason.web"/>
<!--启动Spring MVC的注解功能,设置编码方式,防止乱码-->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class = "org.springframework.http.converter.StringHttpMessageConverter">
<property name = "supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<!--对模型视图名称的解析,即在模型视图名称添加前后缀InternalResourceViewResolver-->
<!--默认的就是JstlView所以这里就不用配置viewClass -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/pages/"
p:suffix=".jsp" />
</beans>
在controller层,我们建立一个logincontroller进行获取message,并返回jason对象给客户端,这样便于我们观察
package com.jason.web;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jason.util.MessageSourceHelper;
@Controller
public class LoginController {
/**
* jump into the index page
*
* @return
*/
@RequestMapping(value = "/index.html")
public String loginPage() {
return "index";
}
/**
* get Messages
*
* @return
*/
@RequestMapping(value = "/message.html")
@ResponseBody
public Map<String, String> getMessage(HttpServletRequest request, HttpServletResponse respone) {
String errorMessage = MessageSourceHelper.getMessage("message.codeTest", new Object[] {"sucess"}, "code test,I use US version operation", request.getLocale());
Map<String, String> map = new HashMap<String, String>();
map.put("message",errorMessage);
return map;
}
}
在jsp页面中,代码如下,这代码包含了标签和代码国际化的常见方式。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="/common/taglibs.jsp"%>
<html>
<head>
<title>Spring login Demo</title>
<script type="text/javascript">
function ajaxTestMessage()
{
$.ajax( {
type : 'GET',
//contentType : 'application/json',
url : '${basePath}/message.html',
async: true,
dataType : 'json',
success : function(data,textStatus){
alert(JSON.stringify(data));
},
error : function(data,textstatus){
alert(data.responseText);
}
});
}
</script>
</head>
<body>
<div>
messages.properties: <font color="red"><spring:message code="message.springtagTest"/></font>
</div>
<div>
messages.properties: <font color="red"><fmt:message key="message.fmttagTest"/></font>
</div>
<div>
messages.properties: <fmt:message key="message.codeTest"><fmt:param value="paraments test"/></fmt:message>
</div>
<div>
messages.properties:<input type=button value="code internationalization Test" οnclick="ajaxTestMessage();"></input>
</div>
<div>
errors.properties: <font color="red"><spring:message code="errors.springtagTest"/></font>
</div>
<div>
errors.properties: <font color="red"><fmt:message key="errors.fmttagTest"/></font>
</div>
</body>
</html>
运行程序,查看下国际化信息,如下:
各种信息都呈现在面前,至此,国际化问题完整了。