Spring核心——MessageSource實現國際化

Spring的國際化

上下文與IoC對ApplicationContext以及Context相關的設計模式進行了介紹。ApplicationContext做爲一個Context在應用的運行層提供了IoC容器、事件、國際化等功能接口。java

Spring的國際化(i18n)功能是經過MessageSource接口實現的,他提供了MessageSource::getMessage方法從預設的資源中獲取對應的數據。git

Java標準資源綁定

在介紹MessageSource以前,得先說清楚Java(J2SE)對國際化的基本實現——ResourceBundle,由於MessageSource是用它實現的。ResourceBundle很好理解,他就是按照規範的格式放置*.properties資源文件,而後根據輸入的語言環境來返回資源。看一個代碼例子就很容易明白了。web

(可執行代碼請到gitee下載,本文的示例代碼在chkui.springcore.example.hybrid.i18n包中。)spring

咱們有3個資源文件放置在classpath的根目錄(本例是放在src/main/resource)中,文件名分別爲i18n_en_US.propertiesi18n_zh_CN.propertiesi18n_web_BASE64.properties。文件中的內容以下:apache

#i18n_en_US.properties
say=Hallo world!

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

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

而後咱們經過ResourceBundle類來使用這些i18n的資源文件:設計模式

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的開發人員作了一些靜態的預設。ide

除了預設內容的Locale,咱們還能夠像Locale locale = new Locale("web", "BASE64")這樣添加自定義的內容,他對應名爲i18n_web_BASE64.properties的資源文件。ui

MessageSource的使用

MessageSource的功能就是用Java標準庫的ResourceBundle實現的,因此使用起來也差很少。this

首先得將用於處理國際化資源的Bean添加到IoC容器中:

@Configuration
public class I18nApp {
	@Bean("messageSource")
	ResourceBundleMessageSource resourceBundleMessageSource() {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		messageSource.setBasenames(new String[] { "i18n", "extend" });//添加資源名稱
		return messageSource;
	}
}

<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方法獲取對應的資源了:

@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文件,文件內容以下:

info={0}\u5E05\u7684\u8BA9\u4EBA\u6CA1\u813E\u6C14\u3002

文件中的{0}表示這個位置用數組中的[0]位置的元素替換。

還有一點須要注意的是,*.properties文件輸入中文等UTF-8的符號時須要保留上面這種ACS的格式,如今大部分IDE都會自動處理的,切記不要爲了方便看內容將*.properties的編碼格式切換爲UTF-8。

獲取MessageSource接口

咱們有三種方式獲取MessageSource接口:

//直接使用
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。

相關文章
相關標籤/搜索