“国际化信息”也称为“本地化信息”,一般需要两个条件才可以确定一个特定的类型的本地化信息
1、语言类型
2、国家/地区类型
java是通过java.util.Locale类表示一个本地化对象。
//带有语言和国家/地区信息的本地化对象 Locale locale = new Locale("zh", "CN");//zh_CN //只有语言信息的本地化对象 Locale locale1 = new Locale("zh");//zh //等同于new Locale("zh", "CN") Locale china = Locale.CHINA;//zh_CN //等同于new Locale("zh") Locale chinese = Locale.CHINESE;//zh //获取本地系统默认的本地化对象 Locale defaultLocale = Locale.getDefault();//zh_CN
jdk的java.text包中提供了本地化支持的工具类,NumberFormat,DateFormat,MessageFormat
String patter="{0},你好,你在{1}银行存入{2}元"; Object[] params={"John",new GregorianCalendar().getTime(),1.0E3}; //使用默认本地化对象格式化信息 String format = MessageFormat.format(patter, params); //使用指定的本地化对象格式化信息 MessageFormat messageFormat = new MessageFormat(patter, Locale.US); String format_local = messageFormat.format(patter, params);
spring定义了访问国际化信息的MessageSource接口,并提供几个易用的实现类。
MessageSource被HierarchicalMessageSource和ApplicationContext接口扩展
HierarchicalMessageSource接口的实现类情况如下图
HierarchicalMessageSource最主要的两个实现类是ResourceBundleMessageSource和ReloadableResourceBundleMessageSource。他们是基于java的ResourceBundle基础类实现,允许通过资源名加载国际化资源
ReloadableResourceBundleMessageSource提供了定时刷新功能,允许在不重启系统的情况下,更新资源信息。
StaticMessageSource用于程序测试,允许通过编程的方式提供国际化信息。DelegatingMessageSource为了方便操作父MessageSource提供的代理类。
一、解析ResourceBundleMessageSource实现
1、定义资源文件
messages.properties
test=test
messages_zh_CN.properties
test=测试
使用native2ascii 将messages_zh_CN.properties的汉子编码转换为ascii,并将messages_zh_CN_tem.properties里的内容拷贝到messages_zh_CN.properties中
native2ascii -encoding utf8 messages_zh_CN.properties messages_zh_CN_tem.properties
2、定义配置文件
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages"/> </bean>ApplicationContext sc=new ClassPathXmlApplicationContext("beans.xml"); Object[] params={}; String test = sc.getMessage("test", params, Locale.CHINA);
二、源码分析
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (beanFactory.containsLocalBean("messageSource")) {
//如果在配置中已经配置了messageSource,将该bean取出来,记录在this.messageSource
this.messageSource = (MessageSource)beanFactory.getBean("messageSource", MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource)this.messageSource;
if (hms.getParentMessageSource() == null) {
hms.setParentMessageSource(this.getInternalParentMessageSource());
}
}if (this.logger.isTraceEnabled()) {
this.logger.trace("Using MessageSource [" + this.messageSource + "]");
}
} else {
//如果用户没有定义配置文件,那么临时使用DelegatingMessageSource以便作为
//getMessage()方法返回
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(this.getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton("messageSource", this.messageSource);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No 'messageSource' bean, using [" + this.messageSource + "]");
}
}}
String test = sc.getMessage("test", params, Locale.CHINA);public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException { //this.getMessageSource是initMessageSource方法中记录取出messageSource的bean return this.getMessageSource().getMessage(code, args, locale); }
通过读取并将自定义资源文件配置记录在容器中,那么就可以在获取资源文件的时候直接使用了。