天天看點

009-Spring IoC 國際化(i18n)MessageSource接口ApplicationContext與MessageSource的關系加載MessageSource(Java配置方式)在resource目錄添加如下兩個配置檔案demo結果在容器管理的Bean中使用MessageSourcemessage配置中的占位符Demo

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配置中可以使用占位符

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接口