【Spring】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官方开发手册,很详尽的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值