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

1.Java中的国际化
国际化(Internationalization)简称 i18n,简单来说就是不同国家/地区/语言的用户,访问同一个程序,得到对应的本地化资源。

首先要确定国家/地区/语言(Locale类)

然后根据不同的Locale获取对应的本地化资源(locale敏感的)。

而本地化资源相关的主要有两种:ResourceBundle和Format抽象类的子类。
①Jdk为ResourceBundle抽象类提供了两个子类(ListResourceBundle和PropertyResourceBundle)

当然也可以参考ResourceBundle编写自定义的子类MyResources和XMLResourceBundle等(源码注释部分)。

(FORMAT_DEFAULT默认使用java.class和java.properties两种格式)其中properties的命名规则basename_language_country.properties。

 

②Format,相对简单不再过多描述。

Format子类中关于Local的使用。

2.Spring中的国际化

首先说明Spring中国际化的支持是AbstractApplicationContext中定义的默认bean(ApplicationContext实现了MessageSource接口),  private MessageSource messageSource;

而在基于Spring的Web应用中使用我们更多关注的是如何确定Local的问题,而对资源的获取则更多的是基于配置。
①通过LocaleResolver获取Local

  • 读取客户端浏览器的默认语言,根据Request Headers中的Accept-language来判断。
  • 客户端传参,并基于Session和Cookie的对Local进行管理(例如一些网站的语言切换选项)。

使用RequestContextUtils.getLocale(request)获取Local;

参考DispatcherServlet的initLocaleResolver()方法,在bean中配置不同的LocaleResolver实现

②通过MessageSource获取ResoureBundle

  • 对与一些简单的资源,我们可以采用properties中配置
  • 在Web应用中,如果资源文件过多,使用properties维护将是个麻烦,可以采用数据库存储结合缓存技术实现。

③messageResoure的配置

核心是AbstractApplicationContext中initMessageSource()中涉及的HierarchicalMessageSource接口;

 

由AbstractBeanFactory中的containsLocalBean(String name)区分为两类:使用配置的HierarchicalMessageSource实现和DelegatingMessageSource(HierarchicalMessageSource的简单实现)

而在messageSource配置class时,有两个常用的HierarchicalMessageSource实现可供选择:ResourceBundleMessageSource和ReloadableResourceBundleMessageSource

两者都是利用资源名通过getMessage()接口就可以加载整套的国际化资源文件,唯一区别在于ReloadableResourceBundleMessageSource可以定时刷新资源文件,以便在应用程序不重启的情况下感知资源文件的变化。很多生产系统都需要长时间持续运行,系统重启会给运行带来很大的负面影响,这时通过该实现类就可以解决国际化信息更新的问题。上面的配置中cacheSeconds属性让ReloadableResourceBundleMessageSource每5秒钟刷新一次资源文件(在真实的应用中,刷新周期不能太短,否则频繁的刷新将带来性能上的负面影响,一般不建议小于30分钟)。cacheSeconds默认值为-1表示永不刷新,此时,该实现类的功能就蜕化为ResourceBundleMessageSource的功能。

 ④简单的代码示例

a.在spring配置文件中定义messageSource<bean>

b.定义不同Local的properties文件,命名规则basename_language_country.properties和java中的一致。

c.代码

  ApplicationContext applicationContext=new FileSystemXmlApplicationContext("classpath:spring-config.xml");
      String message=applicationContext.getMessage("HelloWorld",new Object[]{"hello",new Date()}, Locale.CHINA);

小结:可以看出使用spring的国际化更加灵活(ReloadableResourceBundleMessageSource的动态读取),基于MessageFormat的参数化列表,以及中文支持可以设置编码格式(java中处理相对麻烦)。

 3.总结

Java中:重点了解ResoureBundle的使用参考源码解析图。

Spring中:重点分两部分,①通过LocaleResolver获取Local,②通过通过MessageSource获取ResoureBundle

Spring的国际化是基于Java(Jdk)国际化的扩展,在Web项目中使用更加灵活。

阅读Java(其实这里使用Jdk更合适)源码还能够捋清思路,Spring源码阅读着有些吃力,目前阶段只能结合一些博客挑重点部分的源码进行解读了。

4.参考资料

spring学习4-国际化

利用Spring进行项目国际化(多语言)

 

posted @ 2019-08-20 20:47  Masting  阅读(8005)  评论(0编辑  收藏  举报