spring 如何動態加載properties文件的內容


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(需要入參HttpServletRequest request) ServletContext servletContext = request.getSession() .getServletContext(); WebApplicationContext ctx = WebApplicationContextUtils .getRequiredWebApplicationContext(servletContext);

3. 通過WebApplicationContext獲取中鍵值 String msg = ctx.getMessage("jdbc.url", null, Locale.CHINA);

----------------------------------------------------------------------------------------------------------------

Spring的MessageSource有兩個常用的實現 ReloadableResourceBundleMessageSourceResourceBundleMessageSource。這兩個類在配置上有些區別。
 
我原來常用 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>
 
在比較一下 ReloadableResourceBundleMessageSource 的配置:
<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下的Message。 該設置默認為True,也就是說,如果找不到相應的ResourceBundle,系統始終會顯示為中文的Resource, 建議關掉該設置,否則fallBackLocale久沒有什么意義了
 
另外還有一個有用的設置“ useCodeAsDefaultMessage”, 默認為false,這樣當Spring在ResourceBundle中找不到messageKey的話,就拋出NoSuchMessageException,把它設置為True,則找不到不會拋出異常,而是使用messageKey作為返回值。
----------------------------------------------------------------------------------
spring中ResourceBundleMessageSource與ReloadableResourceBundleMessageSource查找資源的區別: 

1.ResourceBundleMessageSource在xml配置中無法指定編碼: 

     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

     <property name="basenames"> 

          <list> 

               <value >error</value > 

               <value >message</value > 

          </list>       

         </property> 

     </bean> 

而ReloadableResourceBundleMessageSource可以指定編碼,譬如: 

     <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 

        <property name="defaultEncoding" value ="gbk" /> 

        <property name="basename" value ="message" /> 

</bean> 

2.加載資源文件的方式不同: 

1).下面看下它們的源代碼: 

ResourceBundleMessageSource的加載,使用ClassUtils.getDefaultClassLoader()加載器,getDefaultClassLoader的方法代碼如下: 

p lic 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; 



//這種方式也是JVM默認的加載方式,先從當前線程中獲取類加載器,如果沒有,就獲取這個類本身的類加載器 

2).ReloadableResourceBundleMessageSource默認也使用ClassUtils.getDefaultClassLoader()加載器,它加載資源的方式如下: 

p lic 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); 

    } 



3). 小結:ResourceBundleMessageSource從classloader中加載資源文件,可以找到, 

ReloadableResourceBundleMessageSource加載時,默認使用DefaultResourceLoader,他會先判斷資源path是否帶有classpath:前綴,如果有,用 ClassPathResource去加載資源文件,如果沒有試着用文件協議的url去訪問,再沒有就在contextPath即WEB-INF下查找。 

下面做一個Spring的MessageSource的示例: 

1.我們單獨新建一個spring消息文件beans-message.xml中加如下配置: 

   <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 

       <property name="basenames"> 

            <list> 

                 <value >error</value> 

                 <value >message</value > 

            </list> 

       </property> 

   </bean> 

2.這段配置假定在你的classpath中有兩個資源文件(resource bundle),它們是error, message。通過ResourceBundle,使用JDK中解析消息的標准方式,來處理任何解析消息的請求。出於示例的目的,假定 message_zh_CN.properties的資源文件的內容為… 

msg.common.serverBusy = \非\常\抱\歉,\系\統\十\分\繁\忙\! 

#非常抱歉,系統十分繁忙! 

msg.argument.required={0}\是\個\必\填\項\! 

#{0}是個必填項! 

3.再寫一個測試類: 

p lic class MessageTest { 

     p lic static void main(String[] args) { 

         MessageSource resources = new ClassPathXmlApplicationContext("beans-message.xml"); 

         String message = resources.getMessage("msg.common.serverBusy", null, "Default", null); 

         System.out.println(message); 

         String message1 = resources.getMessage("msg.argument.required", new Object[] { "'聯系方式'" }, null, Locale.CHINA); 

         System.out.println(message1); 

     } 



結果輸入為: 

非常抱歉,系統十分繁忙! 

'聯系方式'是個必填項! 

3.在我們的項目中,MessageSource不會單獨使用,通常我們會把它和自己的業務一起使用,這時候我們可以直接用它本身的方法,我們也可以在其中加入我們自己的邏輯:如,自定義的一個消息類: 

p lic class MessageSourceHelper { 

     private ResourceBundleMessageSource messageSource; 

     p lic String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { 

         String msg = messageSource.getMessage(code, args, defaultMessage, locale); 

         return msg != null ? msg.trim() : msg; 

     } 

     

     p lic 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> 

4.我們可以在MessageSourceHelper中加入自己的業務,注入依賴后,就可以在其他類中調用MessageSourceHelper中的方法。 

5.理論簡要: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):本質上和上一個方法相同,其區別在:沒有指定默認值,如果沒找到消息,會拋出一個NoS hMessageException異常。 

     · 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會用得更多一些


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM