Spring加载classpath与classpath*的过程剖析

时间:2022-01-25 18:46:52

使用spring-boot 1.5.7 

在resource目录下创建i18n文件夹

使用spring的默认配置没有加载到文件

# INTERNATIONALIZATION (MessageSourceAutoConfiguration)
spring.messages.always-use-message-format=false # Set whether to always apply the MessageFormat rules, parsing even messages without arguments.
spring.messages.basename=messages # Comma-separated list of basenames, each following the ResourceBundle convention.
spring.messages.cache-seconds=-1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever.
spring.messages.encoding=UTF-8 # Message bundles encoding.
spring.messages.fallback-to-system-locale=true # Set whether to fall back to the system Locale if no files for a specific Locale have been found.

 

在 MessageSourceAutoConfiguration中看到如下代码:

Spring加载classpath与classpath*的过程剖析

 

不是很明白classpath*是什么意思
PathMatchingResourcePatternResolver中的方法实现
    @Override
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern,
"Location pattern must not be null");
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
// a class path resource (multiple resources for same name possible)
       // CLASSPATH_ALL_URL_PERFIX = "classpath*";   
       //getPathMatcher().isPattern("messages.properties") 返回false
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
// a class path resource pattern
return findPathMatchingResources(locationPattern);
}
else {
// all class path resources with the given name
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
// Generally only look for a pattern after a prefix here,
// and on Tomcat only after the "*/" separator for its "war:" protocol.
int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
locationPattern.indexOf(
":") + 1);
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
// a file pattern
return findPathMatchingResources(locationPattern);
}
else {
// a single resource with the given name
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}

 

 

解决方法:

    @Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource
= new ReloadableResourceBundleMessageSource();
messageSource.setBasename(
"classpath:i18n/messages");
messageSource.setDefaultEncoding(
"UTF-8");
return messageSource;
}

 

ResourceBundleMessageSource限制了我们只能将对应的资源文件放置在类路径下

ReloadableResourceBundleMessageSource允许我们指定非类路径下的文件作为对应的资源文件