Spring学习系列——Spring中的国际化

Posted masting

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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进行项目国际化(多语言)

 

以上是关于Spring学习系列——Spring中的国际化的主要内容,如果未能解决你的问题,请参考以下文章

开发人员建议阅读:Spring Boot 架构中的国际化支持实践

0源码基础学习Spring源码系列——Spring如何解决循环依赖

(来换项目系列)Spring学习笔记

不一样的视角来学习Spring源码之容器与Bean---上

Spring Data 系列学习Spring Data JPA 自定义查询,分页,排序,条件查询

Spring 学习笔记——IoC容器(ApplicationContext)