码迷,mamicode.com
首页 > 编程语言 > 详细

spring(11)------spring国际化支持

时间:2016-04-10 14:45:32      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

一,关于spring国际化的简介

在java编程中,对于信息的处理一般有两种方式:

(1)将信息存在数据库里,用的时候从数据库里取。(惯用手法数据字典就是)

(2)将信息存放在java常量类中,通过java类调用属性值。

这两种方式对于处理不需要国际化的网站,系统是能实现的,但是,如果需要国际化,

这两种方式就实现国际化非常困难。

而spring对于国际的实现提供了良好的支持,Application通过继承

org.springframework.context.MessageResource接口,通过getMessage()方法获取信息资源,

从而实现国际化的目的。

二,getMessage()三种形式

(1)getMessage(java.lang.String arg0, java.lang.Object[] arg1, java.lang.String arg2, java.util.Locale arg3);

这个是获取信息的基本方法,如果找不到指定信息,也就是java.lang.Object[] arg1传入后没有找到,

就用java.lang.String arg2这个信息作为默认信息。

(2)getMessage(java.lang.String arg0, java.lang.Object[] arg1, java.util.Locale arg2) throws org.springframework.context.NoSuchMessageException;

跟上一个方法同的是没有指定默认值,如果根据传入参数找不到指定信息,就会抛异常NoSuchMessageException。

(3)getMessage(org.springframework.context.MessageSourceResolvable arg0, java.util.Locale arg1) throws org.springframework.context.NoSuchMessageException;

通过MessageSourceResolvable获取传入信息的信号,传入参数跟上面两个方法类型不一样,一般不常用。

三,spring关于国际化的实现思路

当ApplicationContext被加载的时候,会自动从spring配置文件XML中去查找id为messageSource的bean。

spring约定国际化支持的bean为messageSource,通过org.springframework.context.support.ResourceBundleMessageSource
绑定国际化信息的资源文件,获取国际化信息。

四,简单体验下spring国际化,让后再根据实例分析国际化的实现思想

用输出中文做测试

我的项目结构:

技术分享

messages_en_CN.properties文件内容:

HelloWorld=问候:{0},问候时间:{1} 注意:该文件放在src下

技术分享


HelloWorld类:

package com.lanhuigu.spring.action;



public class HelloWorld{
	private String msg;
	//private RefTest refTest;
	//有参构造器
	/*public HelloWorld(RefTest refTest){
		this.refTest = refTest;
	}*/
	//通过set方法注入属性值
	public void setMsg(String msg) {
		this.msg = msg;
	}
	
	public String getMsg() {
		return msg;
	}

	/*public RefTest getRefTest() {
		return refTest;
	}

	public void setRefTest(RefTest refTest) {
		this.refTest = refTest;
	}*/
	
}
spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<!--
  - Application context definition for JPetStore's business layer.
  - Contains bean references to the transaction manager and to the DAOs in
  - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
  -->
<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"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
	<!-- 负责国际化支持 -->
	<bean id="messageSource" 
		class="org.springframework.context.support.ResourceBundleMessageSource">
		<!-- property有两个属性名,basename,basenames
		               顾名思义,第一个放一个value,第二个放一个或多个value -->
		<property name="basename">
			<!-- 国际化支持的定义在文件名为message的文件中,
				   也就是这个地方设置什么,src下对应的配置文件为
				 messages.properties或 messages.class,
				 名字是别的也一个含义-->
			<value>messages_en_CN</value>
		</property>	
		<!-- <property name="basenames">
			<list>
				<value>messgaes</value>
				<value>error</value>
			</list>
		</property> -->
	</bean>
	
	<!-- 定义一个id为sayHello的bean,
	通过spring配置文件变换实现类,实现不同的功能,无需修改别的程序 -->
	<bean id="sayHello" class="com.lanhuigu.spring.action.HelloWorld" >
		<!-- 将变量msg值依赖注入 -->
	    <property name="msg">
	    	<value>测试</value>
		</property>  
		<!-- refTest为HelloWorld的一个属性,通过ref指定依赖关系,
			也就是说你依赖于哪个类,或者接口,直接把这个类通过set方式注入 ,
			看看HelloWorld的属性定义就明白了-->
		<!-- <property name="refTest">
			<ref bean="refTest"/>
		</property> --> 
	</bean>
	<!-- RefTest类 -->
    <!-- <bean id="refTest" class="com.lanhuigu.spring.action.RefTest">
		myRef为RefTest类的一个属性
		<property name="myRef">
			<value>依赖关系测试</value>
		</property>
	</bean> --> 
</beans>
测试程序:

package com.lanhuigu.spring.test;

import java.util.Calendar;
import java.util.Locale;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.lanhuigu.spring.action.HelloWorld;

public class TestHelloWorld {
	@Test
	public void testMyHelloWorld(){
		//1 读取spring初始化的配置文件
		ApplicationContext acxt = 
				new ClassPathXmlApplicationContext("/applicationContext.xml");
		//2 根据bean获取ISayHello实现类对象
		HelloWorld helloAC = (HelloWorld) acxt.getBean("sayHello");
		//3 调用接口方法
		System.out.println(helloAC.getMsg());
		//4 先获取依赖的类RefTest,在从依赖类中获取依赖类的属性
		//System.out.println(helloAC.getRefTest().getMyRef());
		//5.国际化测试
		//A.对应messages.properties中的两个参数{0},{1}
		Object[] objs = new Object[]{"HelloWorld",Calendar.getInstance().getTime()};
		//B.根据messages.properties中的HelloWorld获取配置,再传入objs数据参数,最后加上国家获取当前时间
		String mytest = acxt.getMessage("HelloWorld", objs, Locale.CHINA);
		System.out.println(mytest);
	}
}
运行结果:

技术分享


输出结果出现乱码的问题,先不管乱码是怎么回事,先根据代码分析国际化原理。

(1)spring配置文件中,国际化bean的id为messageSource(这个是spring约定的,意思是没事别找事,就用它),

bean的来源为org.springframework.context.support.ResourceBundleMessageSource,设定bean中的property

属性basename或basenames两者是有区别的,可以看spring配置文件中的注释,property下value的值就是src

配置文件的名字。例如,在spring中<value>messages_en_CN</value>,即为src国际化信息的配置文件为

messages_en_CN.propertiest或messages_en_CN.class。

(2)messages_en_CN.properties资源文件中的配置为:HelloWorld=问候:{0},问候时间:{1}

=(等号)前的HelloWorld为acxt.getMessage("HelloWorld", objs, Locale.CHINA)相当于key值,

根据HelloWorld获取信息资源配置文件中的(value)‘问候:{0},问候时间:{1}’,然后objs将传入对应的参数,

根据后面的语言组装返回对应的字符串:é?????:HelloWorld,é????????é??:16-4-9 下午7:18(乱码下面解决)


从上面可以看出,国际化就是通过ResourceBundleMessageSource接口获取资源文件,

传入对应参数,组装成对应字符串,也就是把从数据库或java常量类获取信息的形式转换

为从资源库获取信息,如果我们放入不同的资源配置文件,获取的就是不同语言的信息,

从而实现国际化,每次需要什么语言就放什么语言的配置文件。

五,解决中文乱码的问题

在上面的实例中,可以看到,基本的国际化实现了,明明是中文的,输出后是一堆乱码,这个问题解决办法如下:

(1)转码方式解决,吃力不讨好,不去管它

(2)扩展ResourceBundleMessageSource接口,解决乱码问题

在上面util代码下,新建ResourceBundleMessageSourceExtend类,继承于ResourceBundleMessageSource,

处理乱码问题:

package com.lanhuigu.spring.util;

import java.io.UnsupportedEncodingException;  
import java.text.MessageFormat;  
import java.util.Locale;  
import java.util.Map;  
import java.util.concurrent.ConcurrentHashMap;  
  
import org.springframework.context.support.ResourceBundleMessageSource; 

public class ResourceBundleMessageSourceExtend extends  
ResourceBundleMessageSource {  
	//属性文件使用UTF-8编码(你的属性文件messages.properties使用什么进行编码,ENCODING设置成对应的格式)
	private static final String ENCODING = "UTF-8";  
	private static final String NULL = "null";  
	
	/** cache the encoding key value * */  
	Map<String, String> encodingCache = new ConcurrentHashMap<String, String>(  
	    20);  
	
	/** 
	* resolve no argus 
	*/  
	protected String resolveCodeWithoutArguments(String code, Locale locale) {  
		String message = super.resolveCodeWithoutArguments(code, locale);  
		return decodeString(message, ENCODING);  
	
	}  
	
	/** 
	* resolve args 
	* @see resolveCode(String code, Locale locale) 
	*/  
	protected MessageFormat createMessageFormat(String msg, Locale locale) {  
		if (logger.isDebugEnabled()) {  
		    logger.debug("Creating MessageFormat for pattern [" + msg  
		            + "] and locale '" + locale + "'");  
		}  
		msg = decodeString(msg, ENCODING);  
		return new MessageFormat((msg != null ? msg : ""), locale);  
	}  
	
	/** 
	* 转码  
	* @param msg 
	* @param encode 
	* @return 
	*/  
	private String decodeString(String message, String encode) {  
		String encodMessage = encodingCache.get(message);  
		if (encodMessage == null) {  
		    try {  
		        encodMessage = new String(message.getBytes("ISO8859-1"), encode);  
		        if (message != null) {  
		            encodingCache.put(message, encodMessage);  
		        } else {  
		            encodingCache.put(message, NULL);  
		            // log the code is not exist in properties  
		        }  
		    } catch (UnsupportedEncodingException e) {  
		        e.printStackTrace();  
		    }  
		}  
		return encodMessage;  
	}  

}
修改spring配置文件为如下:

<?xml version="1.0" encoding="UTF-8"?>

<!--
  - Application context definition for JPetStore's business layer.
  - Contains bean references to the transaction manager and to the DAOs in
  - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
  -->
<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"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
	<!-- 负责国际化支持 -->
	<bean id="messageSource" 
		class="com.lanhuigu.spring.util.ResourceBundleMessageSourceExtend">
		<!-- property有两个属性名,basename,basenames
		               顾名思义,第一个放一个value,第二个放一个或多个value -->
		<property name="basename">
			<!-- 国际化支持的定义在文件名为message的文件中,
				   也就是这个地方设置什么,src下对应的配置文件为
				 messages.properties或 messages.class,
				 名字是别的也一个含义-->
			<value>messages_en_CN</value>
		</property>	
		<!-- <property name="basenames">
			<list>
				<value>messgaes</value>
				<value>error</value>
			</list>
		</property> -->
	</bean>
	
	<!-- 定义一个id为sayHello的bean,
	通过spring配置文件变换实现类,实现不同的功能,无需修改别的程序 -->
	<bean id="sayHello" class="com.lanhuigu.spring.action.HelloWorld" >
		<!-- 将变量msg值依赖注入 -->
	    <property name="msg">
	    	<value>测试</value>
		</property>  
		<!-- refTest为HelloWorld的一个属性,通过ref指定依赖关系,
			也就是说你依赖于哪个类,或者接口,直接把这个类通过set方式注入 ,
			看看HelloWorld的属性定义就明白了-->
		<!-- <property name="refTest">
			<ref bean="refTest"/>
		</property> --> 
	</bean>
	<!-- RefTest类 -->
    <!-- <bean id="refTest" class="com.lanhuigu.spring.action.RefTest">
		myRef为RefTest类的一个属性
		<property name="myRef">
			<value>依赖关系测试</value>
		</property>
	</bean> --> 
</beans>

其他不变,运行结果如下:

技术分享

乱码好了,这个地方需要注意的就是messages_en_CN.properties编码形式是什么,

扩展接口中得对应了,在propertiest配置文件上右键properties看看编码是啥,然后

设置private static final String ENCODING = "UTF-8";为对应的编码形式,才能避免乱码问题。

我的为UTF-8的形式,所以ENCODING设置成UTF-8,这样做即能支持UTF-8的编码。

技术分享


spring(11)------spring国际化支持

标签:

原文地址:http://blog.csdn.net/yhl_jxy/article/details/51090589

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!