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