国际化主要是引入了MessageSource,我们简单看下如何使用,以及其原理。
1.1 设置资源文件在 properties新建i18n目录
新建message文件:
messages.properties
error.title=Your request cannot be processed
messages_zh_CN.properties
error.title=您的请求无法处理1.2 配置
修改properties文件的目录:在application.yml或者application.properties中配置 spring.message.basename
spring: application: name: test-worklog messages: basename: i18n/messages encoding: UTF-81.3 使用
引用自动注解的MessageSource,调用messageSource.getMessage即可,注意,需要通过LocaleContextHolder.getLocale()获取当前的地区。
@Autowiredprivate MessageSource messageSource;public String getMessage(String result, Object[] params) {
String message = ""; try {
Locale locale = LocaleContextHolder.getLocale();
message = messageSource.getMessage(result, params, locale);
} catch (Exception e) {
LOGGER.error("parse message error! ", e);
} return message;
}如何设置个性化的地区呢? forLanguageTag 即可
Locale locale = Locale.forLanguageTag(user.getLangKey());1.4 原理分析
MessageSourceAutoConfiguration中,实现了autoconfig
@Configuration@ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Conditional(ResourceBundleCondition.class)@EnableConfigurationProperties@ConfigurationProperties(prefix = "spring.messages")public class MessageSourceAutoConfiguration {该类一方面读取配置文件,一方面创建了MessageSource的实例:
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); if (StringUtils.hasText(this.basename)) {
messageSource.setbasenames(StringUtils.commaDelimitedListToStringArray(
StringUtils.trimAllWhitespace(this.basename)));
} if (this.encoding != null) {
messageSource.setDefaultEncoding(this.encoding.name());
}
messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);
messageSource.setCacheSeconds(this.cacheSeconds);
messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat); return messageSource;
}因此,默认是加载的ResourceBundleMessageSource,该类派生与于AbstractResourcebasedMessageSource
@Override
public final String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
String msg = getMessageInternal(code, args, locale); if (msg != null) { return msg;
} if (defaultMessage == null) {
String fallback = getDefaultMessage(code); if (fallback != null) { return fallback;
}
} return renderDefaultMessage(defaultMessage, args, locale);
}最终是调用resolveCode来获取message,通过ResourceBundle来获取message
@Override
protected MessageFormat resolveCode(String code, Locale locale) { // 遍历语言文件路径
Set basenames = getbasenameSet(); for (String basename : basenames) {
ResourceBundle bundle = getResourceBundle(basename, locale); if (bundle != null) {
MessageFormat messageFormat = getMessageFormat(bundle, code, locale); if (messageFormat != null) { return messageFormat;
}
}
} return null;
}
// 获取ResourceBundle protected ResourceBundle getResourceBundle(String basename, Locale locale) { if (getCacheMillis() >= 0) { // Fresh ResourceBundle.getBundle call in order to let ResourceBundle
// do its native caching, at the expense of more extensive lookup steps.
return doGetBundle(basename, locale);
} else { // Cache forever: prefer locale cache over repeated getBundle calls.
synchronized (this.cachedResourceBundles) {
Map localeMap = this.cachedResourceBundles.get(basename); if (localeMap != null) {
ResourceBundle bundle = localeMap.get(locale); if (bundle != null) { return bundle;
}
} try {
ResourceBundle bundle = doGetBundle(basename, locale); if (localeMap == null) {
localeMap = new HashMap(); this.cachedResourceBundles.put(basename, localeMap);
}
localeMap.put(locale, bundle); return bundle;
} catch (MissingResourceException ex) { if (logger.isWarnEnabled()) {
logger.warn("ResourceBundle [" + basename + "] not found for MessageSource: " + ex.getMessage());
} // Assume bundle not found
// -> do NOT throw the exception to allow for checking parent message source.
return null;
}
}
}
}// ResourceBundle protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException { return ResourceBundle.getBundle(basename, locale, getBundleClassLoader(), new MessageSourceControl());
} 最后来看getMessageFormat:
protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale)
throws MissingResourceException { synchronized (this.cachedBundleMessageFormats) { // 从缓存读取
Map> codeMap = this.cachedBundleMessageFormats.get(bundle);
Map localeMap = null; if (codeMap != null) {
localeMap = codeMap.get(code); if (localeMap != null) {
MessageFormat result = localeMap.get(locale); if (result != null) { return result;
}
}
} // 缓存miss,从bundle读取
String msg = getStringOrNull(bundle, code); if (msg != null) { if (codeMap == null) {
codeMap = new HashMap>(); this.cachedBundleMessageFormats.put(bundle, codeMap);
} if (localeMap == null) {
localeMap = new HashMap();
codeMap.put(code, localeMap);
}
MessageFormat result = createMessageFormat(msg, locale);
localeMap.put(locale, result); return result;
} return null;
}
} 作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。



