zoukankan      html  css  js  c++  java
  • 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会用得更多一些
  • 相关阅读:
    生活中头疼脑热及医生诊断用药相关,持续更新
    python3 面试题 英文单词全部都是以首字母大写,逐个反转每个单词
    python 代码如何打包成.exe文件(Pyinstaller)
    charles使用
    经典bug
    python3面试-查找字符串数组中的最长公共前缀
    python3面试题 按规律写出下一个数1,11,21,1211,111221
    python3 测试的时候如何批量随机生成伪数据?(faker模块的)
    python3面试题-一个包含n个整数的数组a,判断a中是否存在三个元素,a,b,c,使得a+b+c=0
    python3面试-将N(N<10000)个人排成一排,从第1个人开始报数;如果报数是M的倍数就出列
  • 原文地址:https://www.cnblogs.com/wnlja/p/3910239.html
Copyright © 2011-2022 走看看