前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring核心——MessageSource实现国际化

Spring核心——MessageSource实现国际化

作者头像
随风溜达的向日葵
发布2018-08-15 11:24:44
4.4K0
发布2018-08-15 11:24:44
举报
文章被收录于专栏:技术墨客技术墨客

Spring的国际化

上下文与IoC对ApplicationContext以及Context相关的设计模式进行了介绍。ApplicationContext作为一个Context在应用的运行层提供了IoC容器、事件、国际化等功能接口。

Spring的国际化(i18n)功能是通过MessageSource接口实现的,他提供了MessageSource::getMessage方法从预设的资源中获取对应的数据。

Java标准资源绑定

在介绍MessageSource之前,得先说清楚Java(J2SE)对国际化的基本实现——ResourceBundle,因为MessageSource是用它实现的。ResourceBundle很好理解,他就是按照规范的格式放置*.properties资源文件,然后根据输入的语言环境来返回资源。看一个代码例子就很容易明白了。

(可执行代码请到gitee下载,本文的示例代码在chkui.springcore.example.hybrid.i18n包中。)

我们有3个资源文件放置在classpath的根目录(本例是放在src/main/resource)中,文件名分别为i18n_en_US.propertiesi18n_zh_CN.propertiesi18n_web_BASE64.properties。文件中的内容如下:

代码语言:javascript
复制
#i18n_en_US.properties
say=Hallo world!

#i18n_zh_CN.properties
say=\u5927\u5BB6\u597D\uFF01

#i18n_web_BASE64.properties
say=+-+-+-ABC

然后我们通过ResourceBundle类来使用这些i18n的资源文件:

代码语言:javascript
复制
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的开发人员做了一些静态的预设。

除了预设内容的Locale,我们还可以像Locale locale = new Locale("web", "BASE64")这样添加自定义的内容,他对应名为i18n_web_BASE64.properties的资源文件。

MessageSource的使用

MessageSource的功能就是用Java标准库的ResourceBundle实现的,所以使用起来也差不多。

首先得将用于处理国际化资源的Bean添加到IoC容器中:

代码语言:javascript
复制
@Configuration
public class I18nApp {
	@Bean("messageSource")
	ResourceBundleMessageSource resourceBundleMessageSource() {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		messageSource.setBasenames(new String[] { "i18n", "extend" });//添加资源名称
		return messageSource;
	}
}

代码语言:javascript
复制
<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方法获取对应的资源了:

代码语言:javascript
复制
@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文件,文件内容如下:

代码语言:javascript
复制
info={0}\u5E05\u7684\u8BA9\u4EBA\u6CA1\u813E\u6C14\u3002

文件中的{0}表示这个位置用数组中的[0]位置的元素替换。

还有一点需要注意的是,*.properties文件输入中文等UTF-8的符号时需要保留上面这种ACS的格式,现在大部分IDE都会自动处理的,切记不要为了方便看内容将*.properties的编码格式切换为UTF-8。

获取MessageSource接口

我们有三种方式获取MessageSource接口:

代码语言:javascript
复制
//直接使用
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。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring的国际化
  • Java标准资源绑定
  • MessageSource的使用
  • 占位符替换
  • 获取MessageSource接口
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档