`

Spring 利用MessageSource实现国际化

阅读更多

Spring 利用MessageSource实现国际化

spring中ResourceBundleMessageSource与ReloadableResourceBundleMessageSource查找资源的区别:

1.ResourceBundleMessageSource在xml配置中无法指定编码:

     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

     <property name="basenames">

          <list>

               <value>error</value>

               <value>message</value>

          </list>      

         </property>

     </bean>

而ReloadableResourceBundleMessageSource可以指定编码,譬如:

     <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

        <property name="defaultEncoding" value="gbk" />

        <property name="basename" value="message" />

</bean>

 

2.加载资源文件的方式不同:

 

1).下面看下它们的源代码:

ResourceBundleMessageSource的加载,使用ClassUtils.getDefaultClassLoader()加载器,getDefaultClassLoader的方法代码如下:

public static ClassLoader getDefaultClassLoader()

{

    ClassLoader cl = null;

    try {

      cl = Thread.currentThread().getContextClassLoader();

   }

    catch (Throwable ex) {

      logger.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex);

    }

    if (cl == null)

    {

      cl = ClassUtils.class.getClassLoader();

    }

    return cl;

}

//这种方式也是JVM默认的加载方式,先从当前线程中获取类加载器,如果没有,就获取这个类本身的类加载器

 

2).ReloadableResourceBundleMessageSource默认也使用ClassUtils.getDefaultClassLoader()加载器,它加载资源的方式如下:

public Resource getResource(String location)

{

    Assert.notNull(location, "Location must not be null");

    if (location.startsWith("classpath:")) {

      return new ClassPathResource(location.substring("classpath:".length()), getClassLoader());

    }

    try

    {

      URL url = new URL(location);

      return new UrlResource(url);

    }

    catch (MalformedURLException ex)

    {

      return getResourceByPath(location);

    }

}

 

3). 小结:ResourceBundleMessageSource从classloader中加载资源文件,可以找到,

ReloadableResourceBundleMessageSource加载时,默认使用DefaultResourceLoader,他会先判断资源path是否带有classpath:前缀,如果有,用ClassPathResource去加载资源文件,如果没有试着用文件协议的url去访问,再没有就在contextPath即WEB-INF下查找。

 

 

下面做一个Spring的MessageSource的示例:

 

1.我们单独新建一个spring消息文件beans-message.xml中加如下配置:

   <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

       <property name="basenames">

            <list>

                 <value>error</value>

                 <value>message</value>

            </list>

       </property>

   </bean>

 

2.这段配置假定在你的classpath中有两个资源文件(resource bundle),它们是error, message。通过ResourceBundle,使用JDK中解析消息的标准方式,来处理任何解析消息的请求。出于示例的目的,假定message_zh_CN.properties的资源文件的内容为…

 

msg.common.serverBusy = \u975E\u5E38\u62B1\u6B49,\u7CFB\u7EDF\u5341\u5206\u7E41\u5FD9\!

#非常抱歉,系统十分繁忙!

msg.argument.required={0}\u\u4E\u5FC5\u586B\u9879\!

#{0}是个必填项!

 

3.再写一个测试类:

public class MessageTest {

     public static void main(String[] args) {

         MessageSource resources = new ClassPathXmlApplicationContext("beans-message.xml");

         String message = resources.getMessage("msg.common.serverBusy", null, "Default", null);

         System.out.println(message);

 

         String message1 = resources.getMessage("msg.argument.required", new Object[] { "'联系方式'" }, null, Locale.CHINA);

         System.out.println(message1);

     }

}

结果输入为:

 

非常抱歉,系统十分繁忙!

'联系方式'是个必填项!

 

3.在我们的项目中,MessageSource不会单独使用,通常我们会把它和自己的业务一起使用,这时候我们可以直接用它本身的方法,我们也可以在其中加入我们自己的逻辑:如,自定义的一个消息类:

public class MessageSourceHelper {

     private ResourceBundleMessageSource messageSource;

     public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {

         String msg = messageSource.getMessage(code, args, defaultMessage, locale);

         return msg != null ? msg.trim() : msg;

     }

    

     public void setMessageSource(ResourceBundleMessageSource messageSource) {

         this.messageSource = messageSource;

     }

}

 

在beans-message.xml中注入:

   <bean id="messageSourceHelper" class="com.myspring.message.MessageSourceHelper">

       <property name="messageSource">

            <ref local="messageSource" />

       </property>

   </bean>

 

4.我们可以在MessageSourceHelper中加入自己的业务,注入依赖后,就可以在其他类中调用MessageSourceHelper中的方法。

 

5.理论简要:ApplicationContext接口扩展了MessageSource接口,因而提供了消息处理的功能(i18n或者国际化)。与HierarchicalMessageSource一起使用,它还能够处理嵌套的消息,这些是Spring提供的处理消息的基本接口。让我们快速浏览一下它所定义的方法:

 

     · String getMessage(String code, Object[] args, String default, Locale loc):用来从MessageSource获取消息的基本方法。如果在指定的locale中没有找到消息,则使用默认的消息。args中的参数将使用标准类库中的MessageFormat来作消息中替换值。

 

     · String getMessage(String code, Object[] args, Locale loc):本质上和上一个方法相同,其区别在:没有指定默认值,如果没找到消息,会抛出一个NoSuchMessageException异常。

 

     · String getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的属性都封装到一个MessageSourceResolvable实现中,而本方法可以指定MessageSourceResolvable实现。

 

当一个ApplicationContext被加载时,它会自动在context中查找已定义为MessageSource类型的bean。此bean的名称须为messageSource。如果找到,那么所有对上述方法的调用将被委托给该bean。否则ApplicationContext会在其父类中查找是否含有同名的bean。如果有,就把它作为MessageSource。如果它最终没有找到任何的消息源,一个空的StaticMessageSource将会被实例化,使它能够接受上述方法的调用。

 

Spring目前提供了两个MessageSource的实现:ResourceBundleMessageSource和StaticMessageSource。它们都继承NestingMessageSource以便能够处理嵌套的消息。StaticMessageSource很少被使用,但能以编程的方式向消息源添加消息。ResourceBundleMessageSource会用得更多一些,

 

6. 更多的资料参考spring官方开发手册,很详尽的!

分享到:
评论

相关推荐

    Grails开源框架 - 使用指南

    不用重新启动服务器就可以进行重新加载利用内置的Spring 容器实现依赖注入基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持基于Spring事务抽象概念,实现事务服务层  借助于功能强大的Groovy动态...

    Spring 2.0 开发参考手册

    3.8.1. 利用MessageSource实现国际化 3.8.2. 事件 3.8.3. 底层资源的访问 3.8.4. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.9.1. 使用Singleton-helper类 4. 资源 4.1. 简介 ...

    使用Grails快速开发Web应用.rar

    不用重新启动服务器就可以进行重新加载利用内置的Spring 容器实现依赖注入基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持基于Spring事务抽象概念,实现事务服务层  借助于功能强大的Groovy动态...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.8.1. 利用MessageSource实现国际化 3.8.2. 事件 3.8.3. 底层资源的访问 3.8.4. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.9.1. 使用Singleton-helper类 4. 资源 4.1. 简介 4.2. ...

    Spring中文帮助文档

    3.8.2. 利用MessageSource实现国际化 3.8.3. 事件 3.8.4. 底层资源的访问 3.8.5. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.10. 以J2EE RAR文件的形式部署Spring ...

    spring chm文档

    3.8.1. 利用MessageSource实现国际化 3.8.2. 事件 3.8.3. 底层资源的访问 3.8.4. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.9.1. 使用Singleton-helper类 4. 资源 4.1. 简介 ...

    Spring API

    3.8.2. 利用MessageSource实现国际化 3.8.3. 事件 3.8.4. 底层资源的访问 3.8.5. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.10. 以J2EE RAR文件的形式部署Spring ...

    GRails 中文帮助文档(参考手册)和安装开发介绍帮助

    基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持 基于Spring事务抽象概念,实现事务服务层 借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变得...

    grails-docs-2.0.3.zip

    基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持 基于Spring事务抽象概念,实现事务服务层 借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变...

    Grails 教程

    基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持 基于Spring事务抽象概念,实现事务服务层 借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变得...

    java中的Grails开源框架 - 使用指南(chm)

    基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持 基于Spring事务抽象概念,实现事务服务层 借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变得...

    grails-开源框架使用指南

    基于Spring的MessageSource核心概念,提供了对国际化(i18n)的支持 基于Spring事务抽象概念,实现事务服务层 借助于功能强大的Groovy动态语言和领域特定语言(Domain Specific Language,DSL),以上那些特性变得...

Global site tag (gtag.js) - Google Analytics