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

一,关于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的编码。

时间: 2024-11-05 23:23:59

spring(11)------spring国际化支持的相关文章

开发人员建议阅读:Spring Boot 架构中的国际化支持实践

pring Boot 主要通过 Maven 或 Gradle 这样的构建系统以继承方式添加依赖,同时继承了 Spring 框架中的优秀元素,减少了 Spring MVC 架构中的复杂配置,内置 Tomcat,Jetty 容器,使用 Java application 运行程序,而不是传统地把 WAR 包置于 Tomcat 等容器中运行,从而简化加速开发流程.此外,Spring Boot 学习简单.轻量级.容易扩展.基于这些优秀的特点,Spring Boot 成为了蓬勃发展的快速应用开发领域的领导者

【Spring】国际化支持

[Spring]国际化支持 一.总体结构: 两个国际化资源中的内容: 二.程序 2.1  配置Spring上下文 beans.xml文件 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema

Spring框架学习六:Spring对JDBC的支持

JdbcTemplate简介 为了使JDBC更加易于使用,Spring 在 JDBC API 上定义了一个抽象层,以此建立一个 JDBC 存取框架 作为 Spring JDBC 框架的核心,JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法.每个模板方法都能控制整个过程,并允许覆盖过程中的特定任务.通过这种方式,可以在尽可能保留灵活性的情况下,将数据库存取工作量降到最低. #添加c3p0数据库连接池 jdbc.user=root jdbc.password=000 jdbc.jd

(四)Spring 对DAO 的支持

第一节:Spring 对JDBC 的支持 1,配置数据源dbcp: 2,使用JdbcTemplate: 3,JdbcDaoSupport 的使用: 4,NamedParameterJdbcTemplate 的使用:支持命名参数变量: org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate 1,使用JdbcTemplate: T.java: 1 package com.wishwzp.test; 2 3 import

11 Spring框架 SpringDAO的JdbcTemplate

上几个章节我们探讨了Spring的IoC和AOP,这是Spring的重点,但是Spring对jdbc的支持同样我们也不能忘记,毕竟我们还要通过Spring来管理DAO框架(例如Hibernate或者MyBatis等). Spring对DAO的支持分为大体可以分为以下两个点: Spring与jdbc模板 Spring对事务的管理 本节我们就来看看第一个知识点: Spring为我们提供了一套jdbc模板,对JDBC进行了一些简单的封装. 想要使用jdbc模板我们首先需要搭建环境: 引入jar包 我们

Spring学习系列(四)——Spring中的国际化

1.Java中的国际化国际化(Internationalization)简称 i18n,简单来说就是不同国家/地区/语言的用户,访问同一个程序,得到对应的本地化资源. 首先要确定国家/地区/语言(Locale类) 然后根据不同的Locale获取对应的本地化资源(locale敏感的). 而本地化资源相关的主要有两种:ResourceBundle和Format抽象类的子类.①Jdk为ResourceBundle抽象类提供了两个子类(ListResourceBundle和PropertyResourc

Spring对远程服务的支持

Java程序有以下的远程调用技术选择: 远程过程调用(RPC)是同步的,客户端在服务器端返回结果之前将一直被阻塞. 各种技术适用的场景如下: 典型的RMI开发的过程如下: 定义一个接口,用于客户端和服务器端的交互,接口要继承Remote接口,所有方法都要抛出RemoteException. 编写服务器端的实现,实现第一步所编写的接口. 编写一个注册类,基于某个某个IP和端口(默认是1099)注册服务器端类的实现. 编写客户端的调用,基于IP,端口和注册的名称查找服务器端对应的类. RMI支持传递

Spring AOP和AspectJ支持

学了Spring之后发现我都不知道java为何物-- 在这一章中有好几节,讲的切面编程 第一节:在项目中启用Spring的AspectJ注解支持 第二节:用AspectJ注解声明aspect 第三节:访问连接点信息 第四节:指定aspect的优先级 第五节:重用切入点定义 第六节:编写AspectJ切入点表达式 第七节:在Bean中引入行为 第八节:为Bean引入状态 第九节:用基于XML的配置声明aspect 如果JVM版本低于1.4时后者不想依赖于AspectJ,就不应该使用AspectJ来

java 利用spring JavaMailSenderImpl发送邮件,支持普通文本、附件、html、velocity模板

java 利用spring JavaMailSenderImpl发送邮件,支持普通文本.附件.html.velocity模板 博客分类: Java Spring 本文主要介绍利用JavaMailSenderImpl发送邮件.首先介绍了发送一般邮件,然后介绍了发送富文本(html)邮件及以velocity为模板发送邮件. 邮件发送分为为三步:创建邮件发送器.编写邮件.发送邮件. Spring的JavaMailSenderImpl提供了强大的邮件发送功能,可发送普通文本邮件.带附件邮件.html格式