1. 在xml中配置properties路徑
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list> <!-- 指定資源檔案基名稱 jdbc為檔案名,不包含擴充名 -->
<value>classpath:resource/jdbc</value>
</list>
</property>
</bean>
2. 擷取WebApplicationContext(需要入參HttpServerletRequest request)
ServletContext servletContext = request.getSession() .getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils .getRequiredWebApplicationContext(servletContext);
3. tongguo WebApplicationContext擷取中鍵值String msg = ctx.getMessage("jdbc.url",null,Locale.CHINA);
Spring的MessageSource有兩個常用的實作ReloadableResourceBundleMesssageSource和ResourceBundleMessageSource.
- ResourceBundleMessageSource:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="parentMessageSource" ref="bizMessageSource" />
<property name = "basenames">
<list>
<value>resources.cls-web-resources</value>
<value>resources.cls-web-resources-definitions</value>
<value>resources.cls-web-resources-menu</value>
</list>
</property>
</bean>
- ReloadableResourceBundleMesssageSource
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="parentMessageSource" ref="bizMessageSource"/>
<property name="fallbackToSystemLocale">
<value>false</value>
</property>
<property name="basenames">
<list>
<value>classpath:resources/cls-web-resources</value>
<value>classpath:resources/cls-web-resources-definitions</value>
<value>classpath:resources/cls-web-resources-menu</value>
</list>
</property>
</bean>
原因:因為ReloadableResourceBundleMessageSource的内部使用DefaultResourceLoader來裝載ResourceBundle, 而ResourceBundleMessageSource内部是直接使用java.util.ResourceBundle.getBundle(String baseName,Locale locale, ClassLoader loader) 來擷取i18n檔案資訊,而ResourceBundle是使用"."來作為basename分隔符的
另外如果不設定"fallbackToSystemLocale"的話, 那麼當傳入的Locale是null或者ResourceBundle沒有改Locale的配置檔案的話, 那麼會傳回Locale.getDefault()的Locale下的Meseage. 該設定預設為True, 也就是說, 如果找不到相應的ResourceBundle, 系統始終會顯示為中文的Resource, 建議關閉該設定, 否則fallBackLocale就沒有什麼意義了.
另外還有一個有用的設定“useCodeAsDefaultMessage”,預設為false,這樣當Spring在ResourceBundle中找不到messageKey的話,就抛出NoSuchMessageException,把它設定為True,則找不到不會抛出異常,而是使用messageKey作為傳回值。
spring中ResourceBundleMessageSource與ReloadableResourceBundleMessageSource查找資源的差別:
- ResourceBundleMessageSource在XML配置中無法指定編碼,而ReloadableResourceBundleMessageSource可以指定編碼
- 加載資源檔案的方式不同:
- ResourceBundleMessageSource的加載,使用ClassUtils.getDefaultClassLoader()加載器,getDefaultClassLoader的方法代碼如下:
這種方式也是JVM預設的加載方式,先從目前線程中擷取類加載器,如果沒有,就擷取這個類本身的類加載器public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); }catch (Throwable ex) { logger.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex); } if (cl == null){ cl = ClassUtils.class.getClassLoader(); } return cl; }
- ReloadableResourceBundleMessageSource預設也使用ClassUtils.getDefaultClassLoader()加載器,它加載資源的方式如下:
public Resource getResource(String location){ Assert.notNull(location, "Location must not be null"); if (location.startsWith("classpath:")) { return new ClassPathResource(location.s string("classpath:".length()), getClassLoader()); } try{ URL url = new URL(location); return new UrlResource(url); }catch (MalformedURLException ex){ return getResourceByPath(location); } }
- 小結:ResourceBundleMessageSource從classloader中加載資源檔案,可以看到:ReloadableResourceBundleMessageSource加載時,預設使用DefaultResourceLoader,他會先判斷資源path是否帶有classpath:字首,如果有,用 ClassPathResource去加載資源檔案,如果沒有試着用檔案協定的url去通路,再沒有就在contextPath即WEB-INF下查找.
- 在項目中,MessageSource不會單獨使用,通常我們會把它和自己的業務一起使用,這時候我們可以直接用它本身的方法,我們也可以在其中加入我們自己的邏輯:如,自定義的一個消息類:
public class MessageSourceHelper {
private ResourceBundleMessageSource messageSource;
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
String msg = messageSource.getMessage(code, args, defaultMessage, locale);
return msg != null ? msg.trim() : msg;
}
public void setMessageSource(ResourceBundleMessageSource messageSource) {
this.messageSource = messageSource;
}
}
在beans-message.xml中注入:
<bean id="messageSourceHelper" class="com.myspring.message.MessageSourceHelper">
<property name="messageSource">
<ref local="messageSource" />
</property>
</bean>
- 我們可以在MessageSourceHelper中加入自己的業務,注入依賴後,就可以在其他類中調用MessageSourceHelper中的方法。
- 理論簡要:ApplicationContext接口擴充了MessageSource 接口,因而提供了消息處理的功能(i18n或者國際化)。與HierarchicalMessageSource一起使用,它還能夠處理嵌套的消息,這些是Spring提供的處理消息的基本接口。讓我們快速浏覽一下它所定義的方法:
- String getMessage(String code, Object[] args, String default, Locale loc):用來從MessageSource擷取消息的基本方法。如果在指定的locale中沒有找到消息,則使用預設的消息。args中的參數将使用标準類庫中的MessageFormat來作消息中替換值。
- String getMessage(String code, Object[] args, Locale loc):本質上和上一個方法相同,其差別在:沒有指定預設值,如果沒找到消息,會抛出一個NoSuhMessageException異常。
- String getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的屬性都封裝到一個MessageSourceResolvable實作中,而本方法可以指定 MessageSourceResolvable實作。
當一個ApplicationContext被加載時,它會自動在context中查找已定義為MessageSource類型的bean。此bean的名稱須為messageSource。如果找到,那麼所有對上述方法的調用将被委托給該 bean。否則ApplicationContext會在其父類中查找是否含有同名的bean。如果有,就把它作為MessageSource。如果它最終沒有找到任何的消息源,一個空的StaticMessageSource将會被執行個體化,使它能夠接受上述方法的調用。
Spring目前提供了兩個MessageSource的實作:ResourceBundleMessageSource和StaticMessageSource。它們都繼承 NestingMessageSource以便能夠處理嵌套的消息。StaticMessageSource很少被使用,但能以程式設計的方式向消息源添加消息。ResourceBundleMessageSource會用得更多一些