您的位置:首页 > 财经 > 金融 > 莆田社交网站_济南制作公司网站_网络营销模式_推广软文300字范文

莆田社交网站_济南制作公司网站_网络营销模式_推广软文300字范文

2024/10/31 17:33:21 来源:https://blog.csdn.net/xsgnzb/article/details/143027954  浏览:    关键词:莆田社交网站_济南制作公司网站_网络营销模式_推广软文300字范文
莆田社交网站_济南制作公司网站_网络营销模式_推广软文300字范文

spring framework提供MessasgeSource来实现国际化。

MessageSource用法

准备properties文件,放在resources文件夹下面。这是默认语言和韩语的文件。

  • i18n/message.properties
  • i18n/message_ko.properties

文件里面的内容是key-value格式,使用{0}、{1}作为变量占位符:

argument.required=The {0} argument is required.

注册MessageSource Bean

spring提供了MessageSource的实现类ResourceBundleMessageSource。它从resources下查找多语言配置,并且会缓存结果。这是spring boot里MessageSource的初始化方法。

@Bean
public MessageSource messageSource(MessageSourceProperties properties) {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();if (StringUtils.hasText(properties.getBasename())) {messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));}if (properties.getEncoding() != null) {messageSource.setDefaultEncoding(properties.getEncoding().name());}messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());Duration cacheDuration = properties.getCacheDuration();if (cacheDuration != null) {messageSource.setCacheMillis(cacheDuration.toMillis());}messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());return messageSource;
}

这里配置了messageSource的几个属性,简单介绍下对应的效果。

  • setBasenames:多语言文件的名字,多个名字用都好隔开。例如要使用上面两个文件,basenames要等于i18n/message。最终是基于basename+local+".properties"找到对应的多语言资源文件。
  • setDefaultEncoding:设置多语言文件里编码格式。默认是ISO-8859-1,要改成UTF-8。
  • setFallbackToSystemLocale:要获取默认Locale时,是不是要返回系统的Locale,也就是Locale.getDefault()。
  • setCacheMillis:控制资源文件文件本地缓存的过期时间,默认-1表示不过期。
  • setAlwaysUseMessageFormat:是否总是使用MessageFormat来解析多语言文本内容。
  • setUseCodeAsDefaultMessage:code不存在时,是否直接返回code值。

使用MessageSource

MessageSource接口提供了三个API:

// 设置参数和默认值
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);// 设置参数
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;// 从多个code中返回第一个找到的值
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

这里都是获取单个code的方法,没有获取数组的API。我们可以参考application.properties里数组的配置方式,增强MessageSource功能。 数组的定义格式:

argument.required[0]=The {0} argument is required. argument.required[1]=The {0} argument is required.

public List<String> getMessageList(String code, Object[] args, Locale locale) {List<String> result = new ArrayList<>();int i = 0;while(true) {val listCode = String.format("%s[%d]", code, i++);String message = getMessage(listCode, args, locale);if (message == null) {break;}result.add(message);}return result;
}

原理介绍

查找code的过程。

  1. 遍历basenames找到对应的资源文件
// 没有变量的情况
protected String resolveCodeWithoutArguments(String code, Locale locale) {Set<String> basenames = getBasenameSet();for (String basename : basenames) {ResourceBundle bundle = getResourceBundle(basename, locale);if (bundle != null) {String result = getStringOrNull(bundle, code);if (result != null) {return result;}}}return null;
}// 有变量的情况,使用MessageFormat对变量进行替换
protected MessageFormat resolveCode(String code, Locale locale) {Set<String> 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;
}
  1. 获得ResourceBundle
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {ClassLoader classLoader = getBundleClassLoader();Assert.state(classLoader != null, "No bundle ClassLoader set");MessageSourceControl control = this.control;if (control != null) {try {return ResourceBundle.getBundle(basename, locale, classLoader, control);}catch (UnsupportedOperationException ex) {// ...}}// Fallback: plain getBundle lookup without Control handlereturn ResourceBundle.getBundle(basename, locale, classLoader);
}
  1. 回调MessageSourceControl.newBundle()加载资源文件 ResourceBundle.getBundle(basename, locale, classLoader, control)方法最终回调control.newBundle()方法来查找资源文件。 MessageSourceControl重写了newBundle(),替换了java.properties的资源查找类型。
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)throws IllegalAccessException, InstantiationException, IOException {// Special handling of default encodingif (format.equals("java.properties")) {String bundleName = toBundleName(baseName, locale);final String resourceName = toResourceName(bundleName, "properties");final ClassLoader classLoader = loader;final boolean reloadFlag = reload;InputStream inputStream = null;if (reloadFlag) {URL url = classLoader.getResource(resourceName);if (url != null) {URLConnection connection = url.openConnection();if (connection != null) {connection.setUseCaches(false);inputStream = connection.getInputStream();}}}else {inputStream = classLoader.getResourceAsStream(resourceName);}if (inputStream != null) {String encoding = getDefaultEncoding();if (encoding != null) {try (InputStreamReader bundleReader = new InputStreamReader(inputStream, encoding)) {return loadBundle(bundleReader);}}else {try (InputStream bundleStream = inputStream) {return loadBundle(bundleStream);}}}else {return null;}}else {// 将 “java.class” 格式的处理委托给标准 Controlreturn super.newBundle(baseName, locale, format, loader, reload);}
}

这里resourceName的格式是{baseName}_{locale}.properties。并且通过reload参数控制,是否重新加载资源文件。 最终用loadBundle(bundleReader)返回PropertyResourceBundle对象。 PropertyResourceBundle会在初始化的时候读取reader里的内容,存到一个Map<String, Object> lookup,后面就拿多语言code去Map里找。找的顺序是先从当前lookup里查,查不到再去parent.lookup里查。

public final Object getObject(String key) {Object obj = handleGetObject(key);if (obj == null) {if (parent != null) {obj = parent.getObject(key);}if (obj == null) {throw new MissingResourceException("Can't find resource for bundle "+this.getClass().getName()+", key "+key,this.getClass().getName(),key);}}return obj;
}

spring文档:Additional Capabilities of the ApplicationContext :: Spring Framework

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com