我正在使用Spring框架为基于Web的应用程序设计一个插件系统。插件是classpath上的jar。这样我就能获得诸如jsp之类的资源,请参见下文
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] pages = resolver.getResources("classpath*:jsp/*jsp");
到现在为止还挺好。但是我对messageSource有问题。在我看来,ReloadableResourceBundleMessageSource#setBasename不通过“ classpath *:” 支持多个类路径。如果仅使用“ classpath:”,则仅从一个插件获取messageSource。
有谁知道如何从所有插件注册messageSources?是否存在这样的MessageSource实现?
这里的问题不是多个类路径或类加载器,而是代码将尝试为给定路径加载多少资源。
该classpath*语法是一种Spring机制,它允许代码为给定路径加载多个资源。非常便利。但是,ResourceBundleMessageSource使用标准java.util.ResourceBundle来加载资源,这是一种更为简单,笨拙的机制,它将为给定路径加载第一个资源,而忽略其他所有内容。
classpath*
ResourceBundleMessageSource
java.util.ResourceBundle
我真的没有一个简单的解决方案。我认为你将不得不放弃ResourceBundleMessageSource并编写一个自定义实现MessageSource(很可能通过子类化AbstractMessageSource),该实现用于PathMatchingResourcePatternResolver定位各种资源并通过MessageSource接口公开它们。ResourceBundle不会有太大帮助。
AbstractMessageSource
PathMatchingResourcePatternResolver
MessageSource
ResourceBundle
通过@ seralex-vi解决方案,基本名称/ 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); }
在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>