spring(11)------spring国际化支持
来源:互联网 发布:恋爱的酸臭味 知乎 编辑:程序博客网 时间:2024/05/29 08:37
一,关于spring国际化的简介
在java编程中,对于信息的处理一般有两种方式:
(1)将信息存在数据库里,用的时候从数据库里取。(惯用手法数据字典就是)
(2)将信息存放在java常量类中,通过java类调用属性值。
这两种方式对于处理不需要国际化的网站,系统是能实现的,但是,如果需要国际化,
这两种方式就实现国际化非常困难。
而spring对于国际的实现提供了良好的支持,Application通过继承
org.springframework.context.MessageResource接口,通过getMessage()方法获取信息资源,
从而实现国际化的目的。
二,getMessage()三种形式
(1)getMessage(String code, Object[] args, String defaultMessage, Locale locale);
这个是获取信息的基本方法,如果找不到指定信息,也就是args传入后没有找到,
就用defaultMessage这个信息作为默认信息。
(2)getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
跟上一个方法同的是没有指定默认值,如果根据传入参数找不到指定信息,就会抛异常NoSuchMessageException。
(3)getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
通过MessageSourceResolvable获取传入信息的信号,传入参数跟上面两个方法类型不一样,一般不常用。
MessageSource源码中getMessage重载了3个方法:
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.context;import java.util.Locale;/** * Strategy interface for resolving messages, with support for the parameterization * and internationalization of such messages. * * <p>Spring provides two out-of-the-box implementations for production: * <ul> * <li>{@link org.springframework.context.support.ResourceBundleMessageSource}, * built on top of the standard {@link java.util.ResourceBundle} * <li>{@link org.springframework.context.support.ReloadableResourceBundleMessageSource}, * being able to reload message definitions without restarting the VM * </ul> * * @author Rod Johnson * @author Juergen Hoeller * @see org.springframework.context.support.ResourceBundleMessageSource * @see org.springframework.context.support.ReloadableResourceBundleMessageSource */public interface MessageSource {/** * Try to resolve the message. Return default message if no message was found. * @param code the code to lookup up, such as 'calculator.noRateSet'. Users of * this class are encouraged to base message names on the relevant fully * qualified class name, thus avoiding conflict and ensuring maximum clarity. * @param args array of arguments that will be filled in for params within * the message (params look like "{0}", "{1,date}", "{2,time}" within a message), * or {@code null} if none. * @param defaultMessage String to return if the lookup fails * @param locale the Locale in which to do the lookup * @return the resolved message if the lookup was successful; * otherwise the default message passed as a parameter * @see java.text.MessageFormat */String getMessage(String code, Object[] args, String defaultMessage, Locale locale);/** * Try to resolve the message. Treat as an error if the message can't be found. * @param code the code to lookup up, such as 'calculator.noRateSet' * @param args Array of arguments that will be filled in for params within * the message (params look like "{0}", "{1,date}", "{2,time}" within a message), * or {@code null} if none. * @param locale the Locale in which to do the lookup * @return the resolved message * @throws NoSuchMessageException if the message wasn't found * @see java.text.MessageFormat */String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;/** * Try to resolve the message using all the attributes contained within the * {@code MessageSourceResolvable} argument that was passed in. * <p>NOTE: We must throw a {@code NoSuchMessageException} on this method * since at the time of calling this method we aren't able to determine if the * {@code defaultMessage} property of the resolvable is null or not. * @param resolvable value object storing attributes required to properly resolve a message * @param locale the Locale in which to do the lookup * @return the resolved message * @throws NoSuchMessageException if the message wasn't found * @see java.text.MessageFormat */String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;}
三,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;//通过set方法注入属性值public void setMsg(String msg) {this.msg = msg;}public String getMsg() {return msg;}}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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://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_en_CN.properties或 messages.class,名字是别的也一个含义--><value>messages_en_CN</value></property><!-- <property name="basenames"><list><value>messages_en_CN</value><value>messages_en_US</value></list></property> --></bean><!-- 定义一个id为sayHello的bean,通过spring配置文件变换实现类,实现不同的功能,无需修改别的程序 --><bean id="sayHello" class="com.lanhuigu.spring.action.HelloWorld" > <!-- 将变量msg值依赖注入 --> <property name="msg"> <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 {@Testpublic 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.国际化测试//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.properties。
(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,
ResourceBundleMessageSourceExtend.java内容如下:
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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://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 name="basename"><value>messages_en_CN</value></property><!-- <property name="basenames"><list><value>messages_en_CN</value><value>messages_en_US</value></list></property> --></bean><bean id="sayHello" class="com.lanhuigu.spring.action.HelloWorld" > <!-- 将变量msg值依赖注入 --> <property name="msg"> <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国际化支持
- Spring 国际化支持
- spring 国际化支持
- spring国际化支持
- Spring支持国际化
- Spring国际化支持
- Spring Boot国际化支持
- Spring Applicationcontext的国际化支持
- Spring Applicationcontext的国际化支持
- Spring对国际化的支持
- Spring学习之国际化支持
- Spring ApplicationContext的国际化支持
- Spring 国际化的支持:Spring MVC Velocity
- Spring -- 国际化的支持(MessageResource用法)
- Spring framework(7):国际化支持 i18n
- Spring国际化
- spring国际化
- spring 国际化
- POJ 3522 Kruskal
- jQuery——小案例:点击图片放大缩小
- easyui + jquery 提交form表单 jquery submit失效
- Android学习之ScrollView使用文档翻译
- 拆分上中下div 且div中嵌套多个横排或竖排div
- spring(11)------spring国际化支持
- 网络:XML 解析之下拉刷新界面(手写代码添加)
- 感知机
- LeetCodet题解--20. Valid Parentheses(括号匹配问题)
- happyxiaofan的程序员书单
- [易飞]此部门不存在或者不是生产部门
- SparkR运行时错误:Re-using existing Spark Context. Please stop SparkR with sparkR.stop() or restart R to c
- 构造函数之二:构造函数常见的使用方式
- 彻底明白IP地址