【问题标题】:Dynamically load files on classpath using ReloadableResourceBundleMessageSource使用 ReloadableResourceBundleMessageSource 在类路径上动态加载文件
【发布时间】:2012-01-27 15:19:48
【问题描述】:

我是 Spring 新手,正在尝试使用它的 ReloadableResourceBundleMessageSource 类。

我正在尝试使用它,以便我们不再需要重新启动我们的网络应用程序来更改/更新属性文件。

我有一个 Web 应用程序(主要使用 JSF)和一个单独的 tar 组件,其中包含我的所有属性文件。

属性tar的结构如下:

 - CompanyOneMessages.properties
 - CompanyOneMessages_fr_FR.properties
 - CompanyTwoMessages.properties
 - CompanyTwoMessages_fr_FR.properties
 - CompanyThreeMessages.properties
 - CompanyThreeMessages_fr_FR.properties
 - ...

此 tar 被解压缩并部署到服务器上指定为在 websphere 配置中的类路径上的位置。

我在 applicationContext-config.xml 中添加了以下内容:

<!-- Enable reloading of resource bundles without requiring web-app restart -->
    <bean id="messages"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>  
                <value>classpath:com/resource/dynamic/CompanyOneMessages</value>
                <value>classpath:com/resource/dynamic/CompanyTwoMessages</value>
                <value>classpath:com/resource/dynamic/CompanyThreeMessages</value>              
            </list>
        </property>     
        <property name="cacheSeconds" value="1" />
    </bean>

    <!-- Declare location of bean to handle messages and define property reference 
         we will use to reference message properties throughout the presentation layer -->
    <bean id="myappMessages" class="com.myapp.resource.MyAPPMessages">
        <property name="messages" ref="messages" />
    </bean>

这一切都很好。

但是,它并没有完全解决原来的问题。 每当我想向我们的应用程序添加新公司时,我都必须在 applicationContext-config.xml 文件中添加新行并重新部署/重新启动 Web 应用程序。

我希望能够简单地将新的公司属性文件拖放到属性 tar 中,然后动态拾取它。

是否可以扩展 ReloadableResourceBundleMessageSource 类,使其在应用程序启动时在类路径中搜索属性文件并动态加载所有这些文件?

更新

这是我目前所拥有的:

applicationContext-config.xml:

<bean id="messages" class="com.resource.MyAPPReloadableResourceBundleMessageSource">
</bean>

MyAPPReloadableResourceBundleMessageSource:

package com.myapp.resource;

import org.springframework.context.support.ReloadableResourceBundleMessageSource;

public class MyAPPReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource
{   
    public MyAPPReloadableResourceBundleMessageSource()
    {   
        getResourceBundlesMessages();

        // Simply single basename test
        setBasename("classpath:/resource/dynamic/companyOneMessages");      
    }

    @Override
    public void setBasename(String baesname)
    {
        System.out.println("In setBasename");
        super.setBasename(baesname);
    }

    @Override
    public void setBasenames(String[] baesnames)
    {
        System.out.println("In setBasenames");
        super.setBasenames(baesnames);
    }

    private String[] getResourceBundlesMessages()
    {
        String[] propertiesFiles = null;

        // How do I get all filenames with .properties under com.resources.dynamic? (location is under classpath)

        return propertiesFiles;
    }
}

所以我只需要如何获取类路径下所有文件的列表,扩展名为 .properties?

谢谢

托马斯

【问题讨论】:

    标签: java spring-mvc resourcebundle


    【解决方案1】:

    ReloadableResourceBundleMessageSource 要求文件位于 webapp/ 目录下,而不是在您的类路径中(它无法重新加载这些文件)。

    【讨论】:

      【解决方案2】:

      您在扩展ReloadableResourceBundleMessageSource 的道路上是正确的。正如@JamesC 提到的,以及ReloadableResourceBundleMessageSource 的 Spring API 文档:

      由于应用程序服务器通常会缓存从类路径加载的所有文件,因此有必要将资源存储在其他地方(例如,在 Web 应用程序的“WEB-INF”目录中)。

      我和你有类似的要求。解决它的关键是扩展ReloadableResourceBundleMessageSource 并覆盖calculateAllFilenames(String basename, Locale locale) 方法来做的不仅仅是将语言代码附加到基本名称。

      例如,如果我的所有外部消息属性文件都在 /srv/myapp/messages 下(在文件系统中,而不是类路径中),则被覆盖的方法将执行以下操作:

      @Override
      protected List<String> calculateAllFilenames(final String basename,
              final Locale locale) {
      
         return super.calculateAllFilenames("file:///srv/myapp/messages/" + basename, 
                 locale);
      }
      

      就我而言,我的basenames 列表是静态的,因此我不必为每个基本名称覆盖调用calculateAllFilenames() 的其他方法。

      在您的特定情况下,我将使用 Company 作为基本名称并覆盖 calculateAllFilenames() 以扫描类路径之外的目录以解析实际的基本名称,然后为每个解析的基本名称调用 super.calculateAllFilenames()(即 super.calculateAllFilenames("file:///path/to/CompanyOneMessages", locale) )。可能,类似于https://stackoverflow.com/a/11223178/1034436 的东西会有所帮助。注意:与引用的答案不同,如果解析的基本名称列表可以动态更改,我不会将目录扫描作为属性设置器的一部分。当然,您的应用的性能考虑也需要考虑在内,因为这显然会大大增加文件系统访问。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-03
        • 2016-06-08
        • 1970-01-01
        • 2023-03-22
        相关资源
        最近更新 更多