009-Spring IoC 国际化(i18n)

MessageSource接口

MessageSource接口定义如下:

package org.springframework.context;

import java.util.Locale;
import org.springframework.lang.Nullable;

public interface MessageSource {
    @Nullable
    String getMessage(String code, @Nullable Object[] args, @Nullable String default, Locale loc);

    String getMessage(String code, @Nullable Object[] args, Locale loc) throws NoSuchMessageException;

    String getMessage(MessageSourceResolvable code, Locale loc) throws NoSuchMessageException;
}

code:配置文件键值
args:配置中的占位符{0}、{1}…的值数组
default:当对应键值不存在时显示的默认值
loc:对应Locale,如Locale.CHINA就是语言

ApplicationContext与MessageSource的关系

ApplicationContext实现了MessageSource接口,我们可以直接通过context实例调用以上方法来实现国际化。
ApplicationContext在加载时与MessageSource相关的代码如下:

protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("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 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 + "]");
            }
        }

    }

该方法在AbstractApplicationContext类中

分析此方法我们知道,ApplicationContext在被加载时会自动搜索容器中是否有名称为messageSource的bean,如果有则加载。如果没有则定义一个空的DelegatingMessageSource类型的MessageSource。

加载MessageSource(Java配置方式)

我们一般通过ResourceBundleMessageSource来加载

package com.yyoo.boot.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;

import java.util.Locale;

@Configuration
@Import({DevConfig.class,TestConfig.class})
@PropertySource({"classpath:test.properties"})
public class AppConfig {

    @Bean("messageSource") // 注意名称必须是messageSource
    public MessageSource getMessageSource(){
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("message");// i18n文件的名称
        messageSource.setDefaultLocale(Locale.US);// 默认语言,如果不设置则为当前系统的语言(建议设置)
        return messageSource;
    }

}

这里我们使用了我们前面定义的AppConfig类,多定义了一个bean而已。

i18n文件的名称规则为 basename_language_country.properties跟java的国际化要求是一致的。

在resource目录添加如下两个配置文件

message_en_US.properties

message=default message

message_zh_CN.properties

message=中文消息

demo

package com.yyoo.boot.annotation;

import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.util.Locale;

public class Demo13 {

    @Test
    public void test(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = context.getEnvironment();
        environment.setActiveProfiles("dev");
        context.register(AppConfig.class);
        context.refresh();

        System.out.println(context.getMessage("message",null, Locale.CHINA));
        System.out.println(context.getMessage("message",null, Locale.US));
        System.out.println(context.getMessage("message",null, Locale.UK));

    }

}

结果

中文消息
default message
default message

第一段和第二段分别打印中文和英文消息,第三段我们的Locale是Locale.UK我们配置文件没有message_en_UK.properties所以它会查询默认的message配置,我们在AppConfig中默认配置的Locale.US所以打印出default message。

如果我们使用了配置文件中没有定义的key值,我们示例的方法将会抛出异常。

如果我们使用context.getMessage(“message1”,null,“默认值”, Locale.CHINA)来调用,那么当message1不存在的时候,将会显示“默认值”

在容器管理的Bean中使用MessageSource

ApplicationContext是MessageSource的实现,我们前面提到过通过@Resource注解或@Autowired注解可以直接注入对应的实例。同理我们的MessageSource也可以。

@Resource
private MessageSource messageSource;

message配置中的占位符

message配置中可以使用占位符

message=您好,{0}。今天是{1}
message=Hello {0}, today is {1}

Demo

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = context.getEnvironment();
environment.setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();

System.out.println(context.getMessage("message",new Object[]{"张三","2021年7月14日 星期三"},"默认值", Locale.CHINA));
System.out.println(context.getMessage("message",new Object[]{"zhangsan","2021/7/14 Wed"},"默认值", Locale.US));

上一篇:008-Spring Ioc 环境与配置
下一篇:010-Spring 资源Resource接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值