(spring-第14回【IoC基础篇】)国际化信息

  国际化又称为本地化。 

  当你把手机的language由中文切换到英文时,你的微信也相应改用英语,这就是i18n国际化。一般来说,应用软件提供一套不同语言的资源文件,放到特定目录中,应用根据不同语言的操作系统决定使用哪一种语言。

  一般由两个条件限定一个国际化类型:语言类型和国家/地区类型。比如:

  中文:语言类型:zh,国家/地区类型:CN(中国大陆)/HK(中国香港)/TW(中国台湾)。

  英语:语言类型:en,国家类型:EN。

----------------------------------------------------------------------------------------------------------------

  java.util.Locale是一个本地化类,是创建国际化应用的基础。

  创建本地化对象有多种方式:Locale locale1=new Locale("zh","CN");//俩参,语言类型、国家类型

               Locale locale2=new Locale("zh");//默认本地语言类型

                 Locale locale3=Locale.CHINA;//常量

               Locale locale4=Locale.getDefault();//默认的本地化对象。

  

  -------------------------------------------------------------------------------------------------------

光有本地化类还不行,需要有个利用本地化对象来操作输出信息的类:

  java.text包中提供了几个这样的工具类:DateFormat、MessageFormat、NumberFormat。

----------------------------------------------------------------------------------------------------  

  NumberFormat举例:给一个123456.78,把它输出为¥123456.78,即把数字转换为货币格式。

1      Locale locale = new Locale("zh","CN");
2         NumberFormat nf=NumberFormat.getCurrencyInstance(locale);
3         System.out.println("一头羊售价:"+nf.format(d));
public static void main(String args[]){
        printCurrency(888.88);
    }

打印:一头羊售价:¥888.88

-------------------------------------------------------------------------------------------------------

DateFormat举例:给一个当前时间Date()对象,把它转换成英文格式。

public static void printUSDate(Date date){
        Locale locale=new Locale("en","US");
        DateFormat df=DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
        System.out.println(df.format(date));
    }

    public static void main(String args[]){
        printUSDate(new Date());
    }

打印:Jan 10, 2016。

上面的DateFormat.MEDIUM是啥?java源码注释:

  /**
     * Constant for long style pattern.
     */
    public static final int LONG = 1;
    /**
     * Constant for medium style pattern.
     */
    public static final int MEDIUM = 2;
    /**
     * Constant for short style pattern.
     */
    public static final int SHORT = 3;
    /**
     * Constant for default style pattern.  Its value is MEDIUM.
     */
    public static final int DEFAULT = MEDIUM;

把参数DateFormat.MEDIUM改成DateFormat.LONG,打印:January 10, 2016。

-------------------------------------------------------------------------------------------------------

MessageFormat:增加占位符功能。

什么是占位符功能?比如:我定义一个字符串:昨天{0}在{1}睡觉呢。传参{"小明","家"},那么打印:昨天小明在家睡觉呢。传参:{"大鹏","学校"},那么打印:昨天大鹏在学校睡觉呢。

举例1:银行给John说:John您好,你于XXX在招商银行存入XX元。不同时间,银行又对David说:David您好,你于XXX在招商银行存入XX元。信息相同,使用MessageFormat。参数信息可以动态改变。

public static void printBankNotice(Object[] params){
        String pattern1="{0},你好,你于{1}在招商银行存入{2}元。";
        String message1=MessageFormat.format(pattern1, params);
        System.out.println(message1);
    }

    public static void main(String args[]){
        printBankNotice(new Object[]{"John",new GregorianCalendar().getTime(),1.0E3});
    }

打印:John,你好,你于16-1-10 上午2:24在招商银行存入1,000元。

占位符功能还能对参数格式作适当的转换,参数顺序也可以灵活调整。

public static void printBankNotice2(Object[] params){
        String pattern2="At{1,time,short} on{1,date,long},{0} paid {2,number,currency}.";
        MessageFormat mf=new MessageFormat(pattern2,Locale.US);
        System.out.println(mf.format(params));
    }

    public static void main(String args[]){
        printBankNotice2(new Object[]{"John",new GregorianCalendar().getTime(),1.0E3});
    }

打印:At2:32 AM onJanuary 10, 2016,John paid $1,000.00.

---------------------------------------------------------------------------------------------------

应用程序中需要国际化,则使用java.util.ResourceBundle

举例:定义一个英文的属性文件和一个中文的属性文件,里面放一些问候语,根据程序的需要选择不同语言的问候语。

步骤:

1.在程序的特定位置定义两个properties文件,一个是中文的,一个是英文的,名称格式为:

<资源名>_<语言代码>_<国家/地区编码>.properties

  resource_en_US.properties内容:

greeting.common=How are you!
greeting.morning = Good morning!
greeting.afternoon =Good Afternoon\!

resource_zh_CN.properties内容:

greeting.common=\u60A8\u597D\uFF01
greeting.morning=\u65E9\u4E0A\u597D\uFF01
greeting.afternoon=\u4E0B\u5348\u597D\uFF01

(资源文件只能包含ASCII字符,所以你这样写了,程序运行时需要把这样的字符转换成Unicode的表示形式。但是这样编写我们不熟悉,也不现实,所以,MyEclipse提供了属性编辑器,可以方便我们写中文):

切换到Properties窗口:

在这里编写就好。

接下来使用ResourceBundle。

public static void resourceBoundle(){
        ResourceBundle rb1 = ResourceBundle.getBundle("com/baobaotao/i18n/resource",Locale.US);
        ResourceBundle rb2 = ResourceBundle.getBundle("com/baobaotao/i18n/resource",Locale.CANADA);
        System.out.println("us:"+rb1.getString("greeting.common"));
        System.out.println("cn:"+rb2.getString("greeting.common"));
    }

上文讲到了占位符功能,在这里,你也可以把properties文件的属性值写成占位符形式,然后用ResourceBundle结合MessageFormat实现国际化字符串的动态改变。

---------------------------------------------------------------------------------------------------------

Spring的国际化

spring定义了MessageSource接口来实现国际化,它引入了java.util.Locale,并用getMessage方法加载国际化信息。也就是说,spring国际化的原理还是引用了上面讲的java的那一套,不过把它引入到了spring容器中。

类图结构:

根据继承关系我们看到,ResourceBundleMessageSource、ReloadableResourceBundleMessageSource、ApplicationContext都具有MessageSource功能。

-----------------------------------------------------------------------------------------------------------------------------------------------

ResourceBundleMessageSource是spring一般的国际化方法类。使用也很简单,

在XML中注册该类,容器启动时就会实例化该类:

 <bean id="myResource1" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
       <list>
         <value>com/baobaotao/i18n/fmt_resource</value>
       </list>
    </property>
  </bean> 

list里面可以放多个properties文件,这里fmt_resource是一个通用名,包含了该名下所有的properties文件,

在代码中,启动spring容器,加载MessageSource,定义格式化串,调用getMessage就可以了:

private static void rsrBdlMessageResource(){

        String[] configs = {"com/baobaotao/i18n/beans.xml"};
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configs);
        //步骤1:获取MessageSource实例化对象
        MessageSource ms = (MessageSource)ctx.getBean("myResource1");
        //步骤2:定义格式化串
        Object[] params = {"John", new GregorianCalendar().getTime()};
        //步骤3:调用getMessage方法啊
        String str1 = ms.getMessage("greeting.common",params,Locale.US);
        String str2 = ms.getMessage("greeting.morning",params,Locale.CHINA);
        String str3 = ms.getMessage("greeting.afternoon",params,Locale.CHINA);
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);

    }

-------------------------------------------------------------------------------------------------

ReloadableResourceBundleMessageSource

跟ResourceBundleMessageSource相比,它多了一个定时刷新功能,即,系统在不重启的情况下,修改properties文件,使用ReloadableResourceBundleMessageSource重新加载(定时)。

在XML中注册bean的时候加一个定时属性就可以了:

 <bean id="myResource2" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
       <list>
         <value>com/baobaotao/i18n/fmt_resource</value>
       </list>
    </property>
    <property name="cacheSeconds" value="2"/>
  </bean>  

---------------------------------------------------------------------------------------------------------

ApplicationContext的国际化功能:

ApplicationContext属于容器级,它赋予了国际化信息功能,是因为国际化信息常常作为容器的公共基础设施对所有组件开放。

使用容器级国际化很简单,针对ResourceBundleMessageSource作一点点修改:

配置文件上的修改:

 <bean id="mySource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
       <list>
         <value>com/baobaotao/i18n/fmt_resource</value>
       </list>
    </property>
  </bean> 

代码修改:

去掉getBean步骤,直接用ctx.getMessage获取字符串。

------------------------------------------------------------------------------------------------------

总结:

  1. 国际化信息又称为本地化信息,由语言类型(如zh)和国家/地区类型来限定(如CN)。
  2. java.util.Locale是创建国际化的基础类。
  3. NumberFormat(对数字转换成特定格式)、DateFormat(对日期输出为特定格式)、MessageFormat(使用占位符)等是操作国际化的工具类。
  4. 使用ResourceBundle类处理针对国际化的properties文件(命名规则有限定,如resource_en_US.properties)。
  5. spring管理国际化定义了MessageSource接口。
  6. ResourceBundleMessageSource实现了MessageSource接口。
  7. ReloadableResourceBundleMessageSource实现了MessageSource接口,多了定时更新国际化信息的功能。
  8. ApplicationContext实现了MessageSource接口,把国际化信息上升到了容器级。

玉不琢,不成器;人不学,不知道。——《礼记·学记》

时间: 2024-11-08 19:20:56

(spring-第14回【IoC基础篇】)国际化信息的相关文章

(spring-第14回【IoC基础篇】)国际化信息 (转)

国际化又称为本地化. 当你把手机的language由中文切换到英文时,你的微信也相应改用英语,这就是i18n国际化.一般来说,应用软件提供一套不同语言的资源文件,放到特定目录中,应用根据不同语言的操作系统决定使用哪一种语言. 一般由两个条件限定一个国际化类型:语言类型和国家/地区类型.比如: 中文:语言类型:zh,国家/地区类型:CN(中国大陆)/HK(中国香港)/TW(中国台湾). 英语:语言类型:en,国家类型:EN. ------------------------------------

(spring-第7回【IoC基础篇】)BeanDefinition的载入与解析&amp;&amp;spring.schemas、spring.handlers的使用

报错信息:Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/p], 一桩事故引发的连锁思考...开幕—— ----------------------------------------------------------------------------------------------

(spring-第9回【IoC基础篇】)BeanFactoryPostProcessor,实例化Bean之前的第二大利器

继承结构图如上.在加载XML,注册bean definition之后,在实例化bean definition之前,必要的时候要用到BeanFactoryPostProcessor.它负责把XML中有些占位符式的属性还原成真实值.意思是说,有时候,XML中<bean>的属性值不固定,会随着外界因素变化,这时候,在<bean>中配置占位符,而另外定义一个属性文件来控制<bean>的属性.比如下面是一个数据库连接的XML配置: 1 <bean id="data

(spring-第13回【IoC基础篇】)PropertyEditor(属性编辑器)--实例化Bean的第五大利器

上一篇讲到JavaBeans的属性编辑器,编写自己的属性编辑器,需要继承PropertyEditorSupport,编写自己的BeanInfo,需要继承SimpleBeanInfo,然后在BeanInfo中把特定的属性编辑器和需要编辑的属性绑定起来(详情请查看上一篇). Spring的属性编辑器仅负责将配置文件中的字面值转换成Bean属性的对应值.(而JavaBean的属性编辑器能够通过界面来手动设置bean属性的值).如果属性的类型不同,转换的方法就不同.正如javabean的属性编辑器一样,

(spring-第12回【IoC基础篇】)JavaBean的属性编辑器

在spring实例化bean的最后阶段,spring利用属性编辑器将配置文件中的文本配置值转换为bean属性的对应值,例如: 代码0011 <bean id="car" class="com.mesopotamia.test1.Car" 2 p:name="汽车" 3 p:brand="宝马" 4 p:maxSpeed="200"/> 上面是文本配置, 再看bean: 代码0021 public

(spring-第8回【IoC基础篇】)BeanDefinition在IoC容器中的注册

在spring中,所有的bean都是由BeanFactory进行管理的.下面是BeanFactory的类体系结构: 我们清楚的看到,DefaultListableBeanFactory继承了BeanFactory的优良传统,同时又实现了BeanDefinitionRegistry这个注册器,那么无疑,BeanDefinition在容器中的注册任务,非他莫属.事实上,DefaultListableBeanFactory拥有一个私有的BeanDefinitonMap属性,这个属性是个哈希Map,通过

(spring-第10回【IoC基础篇】)InstantiationStrategy--实例化Bean的第三大利器

Bean的实例化整个过程如下图: : 其中,BeanDefinition加入到注册表中,并由BeanFactoryPostProcessor的实现类处理后,需要由InstantiationStrategy负责实例化.实例化仅仅是调用构造函数,相当于new了一个对象而已,bean的具体的属性在此时并未赋值(当然,一开始在XML中配置了Bean属性的值,或者在构造函数中有赋值语句的话,相关属性才会在实例化的时候便有了值.).InstantiationStrategy负责由Bean类的默认构造函数.带

(spring-第15回【IoC基础篇】)容器事件

五个人在报社订阅了报纸.报社一旦有了新报纸,就派员工分别送到这五个人手里.在这个例子中,“报纸”就是事件,“报社”就是广播器,五个订阅者就是监听器.广播器收到事件,把事件传给监听器,监听器对事件做一些事情.这样的例子属于观察者模式. 观察者模式:A类负责接收新信息,B.C.D类一直关注着A.A类一旦有了新信息,就发送给B.C.D类,B.C.D类收到信息作出不同的操作.这就是观察者模式.具体到代码中,A中设置一个变量message(这就是信息),当message改变时,调用B.C.D的perfor

Spring+SpringMVC+MyBatis+easyUI整合基础篇(二)牛刀小试

承接上文,该篇即为项目整合的介绍了. 废话不多说,先把源码和项目地址放上来,重点要写在前面. github地址为ssm-demo 你也可以先体验一下实际效果,点击这里就行啦 账号:admin 密码:123456 从构思这个博客,一直到最终确定以这个项目为切入点,中间也是各种问题出现,毕竟是新人,所以也是十分的小心,修改代码以及搬上github其实花了不少时间,但也特别的认真,不知道是怎么回事,感觉这几天的过程比逼死产品经理还要精彩和享受.或许是博客路上的第一站吧,有压力也有新奇,希望自己能坚持下