ResourceBundle
Java 提供了 ResourceBundle 类,能够实现特定区域(语言环境)的资源加载。以便咱们在编码时能够应用一个 ResourceBundle 而不必思考特定的语言环境信息,程序主动通过以后的用户的语言环境信息来加载特定资源。
ResourceBundle 的应用比较简单,如上面的代码。
public class ResourceBundleDemo {public static void main(String[] args) throws UnsupportedEncodingException {ResourceBundle rb = ResourceBundle.getBundle("test");
System.out.println(rb.getString("key1"));
rb = ResourceBundle.getBundle("test", Locale.GERMAN);
System.out.println(rb.getString("key1"));
}
}
ResourceBundle 通过了 getBundle 工厂办法创立的实例默认被缓存。如果 ResourceBundle 被缓存屡次调用 getBundle 办法返回同一个实例。getBundle 的客户端能够革除缓存、治理缓存的缓存工夫。参考:clearCache 办法、ResourceBundle.Control.getTimeToLive 和 ResourceBundle.Control.needsReload。
Java 平台提供了 ResourceBundle 两个子类 ListResourceBundle 和 PropertyResourceBundle。
ResourceBundle 工厂办法在加载资源的过程中须要 ResourceBundle.Control 提供必须要的信息。ResourceBundle.Control 提供包含:bundle 名字、创立 Bundle、资源寻找等信息。默认的 ResourceBundle.Control 能够被笼罩。默认的 ResourceBundle.Control 实现了两种格局资源的加载,class 格局和 properties 格局。例如上面的代码:
ResourceBundle rb = ResourceBundle.getBundle(“MyResource”);
那么会加载 MyResource.class(及相干语言区域后缀的 class),如果 class 找不到,会加载 MyResource.properties(及相干语言区域后缀的 properties) 的相干文件(通过 PropertyResourceBundle)。
MessageFomat
MessageFormat 提供了以与语言无关形式生成连贯音讯的形式。应用此办法结构向终端用户显示的音讯。MessageFormat 自身不实现特定于语言环境的行为。特定于语言环境的行为是由所提供的模式和用于已插入参数的子格局来定义的。
MessageFormat 简略实例如下代码:
int planet = 7;
String event = "a disturbance in the Force";
String result = MessageFormat.format("At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
planet, new Date(), event);
MessageFormat 具体应用以及 pattern 模式能够参考 javadoc。
MessageFormat 能够和 ResourceBundle 配合做到个不同语言环境的用户显示。
public static void main(String[] args) {Date d = new Date();
MessageFormat format = new MessageFormat("明天是 {0,date ,yyyy-MM-dd}");
System.out.println(format.format(new Object[]{d}));
format.applyPattern("today is {0,date, dd/MM/yy}");
System.out.println(format.format(new Object[]{d}));
}
Spring MessageSource
Spring MessageSource 接口,用来反对参数化和国际化音讯。
public interface MessageSource {
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
Spring 提供了两个开箱即用的 MessageSource 实现,ResourceBundleMessageSource 和 ReloadableResourceBundleMessageSource。
在 AbstractApplicationContext 中的 initMessageSource 办法,检测有无配置名称为 MESSAGE_SOURCE_BEAN_NAME(messageSource) 的 bean, 如果没有配置则生成一个 DelegatingMessageSource 进行注册。initMessageSource 的源码如下:
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
*/
protected void initMessageSource() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {logger.trace("No'" + MESSAGE_SOURCE_BEAN_NAME + "'bean, using [" + this.messageSource + "]");
}
}
}
DelegatingMessageSource 仅仅代理 AbstractApplicationContext 父类中的 messageSource 实例,或者父 AbstractApplicationContext(因为 AbstractApplicationContext 实现了 MessageSource 的接口)。
AbstractApplicationContext 也实现了 MessageSource 的接口,相干的实现都是通过委托外部的 messageSource 进行解决的。源码如下:
@Override
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {return getMessageSource().getMessage(code, args, defaultMessage, locale);
}
@Override
public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {return getMessageSource().getMessage(code, args, locale);
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {return getMessageSource().getMessage(resolvable, locale);
}
private MessageSource getMessageSource() throws IllegalStateException {if (this.messageSource == null) {
throw new IllegalStateException("MessageSource not initialized -" +
"call'refresh'before accessing messages via the context:" + this);
}
return this.messageSource;
}
我的项目中,咱们如果想应用国际化的内容,须要配置一个名字为“messageResource”的 MessageResouce 实例,能够应用 spring 开箱即用的现有实现(ResourceBundle 和 MessageFormat 的合集)。