在上下文与IoC对ApplicationContext以及Context相关的设计模式进行了介绍。ApplicationContext做为一个Context在应用的运行层提供了IoC容器、事件、国际化等功能接口。java
Spring的国际化(i18n)功能是经过MessageSource接口实现的,他提供了MessageSource::getMessage方法从预设的资源中获取对应的数据。git
在介绍MessageSource以前,得先说清楚Java(J2SE)对国际化的基本实现——ResourceBundle,由于MessageSource是用它实现的。ResourceBundle很好理解,他就是按照规范的格式放置*.properties资源文件,而后根据输入的语言环境来返回资源。看一个代码例子就很容易明白了。web
(可执行代码请到gitee下载,本文的示例代码在chkui.springcore.example.hybrid.i18n包中。)spring
咱们有3个资源文件放置在classpath的根目录(本例是放在src/main/resource)中,文件名分别为i18n_en_US.properties、i18n_zh_CN.properties和i18n_web_BASE64.properties。文件中的内容以下:apache
#i18n_en_US.properties say=Hallo world! #i18n_zh_CN.properties say=\u5927\u5BB6\u597D\uFF01 #i18n_web_BASE64.properties say=+-+-+-ABC
而后咱们经过ResourceBundle类来使用这些i18n的资源文件:设计模式
package chkui.springcore.example.hybrid.i18n; public class I18nApp { public static void main(String[] args) { //使用当前操做系统的语言环境 ResourceBundle rb = ResourceBundle.getBundle("i18n", Locale.getDefault()); System.out.println(rb.getString("say")); //指定简体中文环境 rb = ResourceBundle.getBundle("i18n", new Locale("zh", "CN")); System.out.println(rb.getString("say")); //经过预设指定简体英文环境 rb = ResourceBundle.getBundle("i18n", Locale.SIMPLIFIED_CHINESE); System.out.println(rb.getString("say")); //指定美国英语 rb = ResourceBundle.getBundle("i18n", Locale.US); System.out.println(rb.getString("say")); //使用自定义的语言环境 Locale locale = new Locale("web", "BASE64"); rb = ResourceBundle.getBundle("i18n", locale); System.out.println(rb.getString("say")); } }
按照开发文档的要求,使用ResourceBundle加载的资源文件都必须放置在根目录,而且必须按照${name}_${language}_${region}的方式来命名。这个命名方式正好能对应ResourceBundle::getBundle方法中的参数,例如ResourceBundle.getBundle("i18n", new Locale("zh", "CN"))。"i18n"对应${name},"zh"定位${language},而“CN”对应${region}。这样咱们就能够经过传导参数来使用不一样的资源。若是不指定${language}和${region},该文件就是一个默认文件。数组
Locale类预设了不少资源类型,好比Locale.SIMPLIFIED_CHINESE、Locale.US,实际上他们就等价于new Locale("zh", "CN")和new Locale("en", "US")。只是Java的开发人员作了一些静态的预设。ide
除了预设内容的Locale,咱们还能够像Locale locale = new Locale("web", "BASE64")这样添加自定义的内容,他对应名为i18n_web_BASE64.properties的资源文件。ui
MessageSource的功能就是用Java标准库的ResourceBundle实现的,因此使用起来也差很少。this
首先得将用于处理国际化资源的Bean添加到IoC容器中:
@Configuration public class I18nApp { @Bean("messageSource") ResourceBundleMessageSource resourceBundleMessageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasenames(new String[] { "i18n", "extend" });//添加资源名称 return messageSource; } }
或
<beans> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>i18n</value> <value>extend</value> </list> </property> </bean> </beans>
切记必定要标记id=messageSource。basenames这个Setter用于指定*.properties资源文件的名称,规则和前面介绍的ResourceBundle同样。而后就能够经过ApplicationContext::getMessage方法获取对应的资源了:
@Configuration public class I18nApp { @Bean("messageSource") ResourceBundleMessageSource resourceBundleMessageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasenames(new String[] { "i18n", "extend" }); return messageSource; } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(I18nApp.class); System.out.println("Spring Default 1:" + context.getMessage("say", null, Locale.getDefault())); System.out.println("Spring Default 2:" + context.getMessage("say", null, null)); System.out.println("Spring Chinese:" + context.getMessage("say", null, Locale.SIMPLIFIED_CHINESE)); System.out.println("Spring Us English:" + context.getMessage("say", null, Locale.US)); System.out.println("Spring Custom:" + context.getMessage("say", null, new Locale("web", "BASE64"))); System.out.println("Spring Argument:" + context.getMessage("info", new String[] {"chkui"},null)); System.out.println("Spring Info:" + context.getMessage("say", null, null)); } }
注意上面的示例代码的这一行:context.getMessage("info", new String[] {"chkui"},null)),这里的getMessage向方法传递了一个数组,他用于替换资源文件中的占位符号。在例子中咱们除了i18n还加载了一个extend.properties文件,文件内容以下:
info={0}\u5E05\u7684\u8BA9\u4EBA\u6CA1\u813E\u6C14\u3002
文件中的{0}表示这个位置用数组中的[0]位置的元素替换。
还有一点须要注意的是,*.properties文件输入中文等UTF-8的符号时须要保留上面这种ACS的格式,如今大部分IDE都会自动处理的,切记不要为了方便看内容将*.properties的编码格式切换为UTF-8。
咱们有三种方式获取MessageSource接口:
//直接使用 ApplicationContext context = new AnnotationConfigApplicationContext(I18nApp.class); context.getMessage("say", null, Locale.getDefault())); //MessageSourceAware(ApplicationContextAware)接口 public class ExtendBean implements MessageSourceAware { @Override public void setMessageSource(MessageSource messageSource) { this.setterMs = messageSource; } } //从容器直接注入 public class ExtendBean implements MessageSourceAware { @Autowired private MessageSource autowiredMs; }
须要注意的是,使用@Autowired等方式直接获取MessageSource类型的数据获得的是添加到容器的那个Bean,而其余方式获取到的是ApplicationContext。