Spring MessageSource是否支持多类路径?

ban*_*rCZ 16 java plugins spring classpath

我正在使用Spring框架为基于Web的应用程序设计插件系统.插件是类路径上的jar.所以我能够得到像jsp这样的资源,见下文

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] pages = resolver.getResources("classpath*:jsp/*jsp");
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但我的messageSource有问题.在我看来,ReloadableResourceBundleMessageSource #setBasename支持通过"classpath*:"的多个类路径.如果我只使用"classpath:",我只从一个插件获取messageSource.

有没有人知道如何从所有插件注册messageSources?是否存在MessageSource的这种实现?

aja*_*sti 17

随着@ seralex-vi basenames/WEB-INF/messages的解决方案无效.

我在类ReloadableResourceBundleMessageSource上覆盖方法refreshProperties,它执行两种类型的基本名称(classpath*:和/ WEB-INF /)

public class SmReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {

private static final String PROPERTIES_SUFFIX = ".properties";

private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

@Override
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
    if (filename.startsWith(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
        return refreshClassPathProperties(filename, propHolder);
    } else {
        return super.refreshProperties(filename, propHolder);
    }
}

private PropertiesHolder refreshClassPathProperties(String filename, PropertiesHolder propHolder) {
    Properties properties = new Properties();
    long lastModified = -1;
    try {
      Resource[] resources = resolver.getResources(filename + PROPERTIES_SUFFIX);
      for (Resource resource : resources) {
        String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
        PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
        properties.putAll(holder.getProperties());
        if (lastModified < resource.lastModified())
          lastModified = resource.lastModified();
      }
    } catch (IOException ignored) { 
    }
    return new PropertiesHolder(properties, lastModified);
}
Run Code Online (Sandbox Code Playgroud)

在spring-context.xml上,您必须具有classpath*:前缀

<bean id="messageSource" class="SmReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>/WEB-INF/i18n/enums</value>
            <value>/WEB-INF/i18n/messages</value>
            <value>classpath*:/META-INF/messages-common</value>
            <value>classpath*:/META-INF/enums</value>
        </list>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

  • 这应该是答案,它提供了一个解决方案,它的工作原理.谢谢 (5认同)

Rag*_*ram 9

您可以执行类似于下面的操作 - 实质上明确指定每个相关的基本名称.

 <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>classpath:com/your/package/source1</value>
                <value>classpath:com/your/second/package/source2</value>
                <value>classpath:com/your/third/package/source3/value>
                <value>classpath:com/your/fourth/package/source4</value>
            </list>
        </property>
    </bean>
Run Code Online (Sandbox Code Playgroud)

  • 恩,那就对了.但是你必须事先了解所有插件.对于插件,洗脱液应该是通用的. (5认同)
  • 你刚刚教我如何在值中输入包路径. (4认同)

ska*_*man 8

这里的问题不是多个类路径或类加载器,而是代码将为给定路径尝试和加载多少资源.

classpath*语法是一个弹簧机构,一个允许的代码来加载多个资源对于给定的路径.非常便利.但是,ResourceBundleMessageSource使用标准java.util.ResourceBundle来加载资源,这是一个更简单的dumber机制,它将加载给定路径的第一个资源,并忽略其他所有内容.

我真的没有一个简单的解决方案.我认为你将不得不放弃ResourceBundleMessageSource并编写一个自定义实现MessageSource(很可能通过子类化AbstractMessageSource),它PathMatchingResourcePatternResolver用于定位各种资源并通过MessageSource接口公开它们.ResourceBundle不会有太大帮助.