int prefixEnd = 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)};
}
}
}
对classpath下的资源,相同名字的资源可能存在多个,如果使用”classpath*:”作为前缀,表明需要找到classpath下所有该名字资源,因而需要调用findClassPathResources方法查找classpath下所有该名称的Resource,对非classpath下的资源,对于不存在模式字符的location,一般认为一个location对应一个资源,因而直接调用ResourceLoader.getResource()方法即可(对classpath下没有以”classpath*:”开头的location也适用)。
findClassPathResources方法实现相对比较简单:
适用ClassLoader.getResources()方法,遍历结果URL集合,将每个结果适用UrlResource封装,最后组成一个Resource数组返回即可。
对包含模式匹配字符的location来说,需要调用findPathMatchingResources方法:
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
String rootDirPath = determineRootDir(locationPattern);
String subPattern = locationPattern.substring(rootDirPath.length());
Resource[] rootDirResources = getResources(rootDirPath);
Set result = new LinkedHashSet(16);
for (int i = 0; i < rootDirResources.length; i++) {
Resource rootDirResource = resolveRootDirResource(rootDirResources[i]);
if (isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
}
else {
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
}
if (logger.isDebugEnabled()) {
logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return (Resource[]) result.toArray(new Resource[result.size()]);
}
1. determinRootDir()方法返回locationPattern中最长的没有出现模式匹配字符的路径
2. subPattern则表示rootDirPath之后的包含模式匹配字符的路径信pattern
3. 使用getResources()获取rootDirPath下的所有资源数组。
4. 遍历这个数组。
a) 对jar中的资源,使用doFindPathMatchingJarResources()方法来查找和匹配。
b) 对非jar中资源,使用doFindPathMatchingFileResources()方法来查找和匹配。
doFindPathMatchingJarResources()实现:
1. 计算当前Resource在Jar文件中的根路径rootEntryPath。
2. 遍历Jar文件中所有entry,如果当前entry名以rootEntryPath开头,并且之后的路径信息和之前从patternLocation中截取出的subPattern使用PathMatcher匹配,若匹配成功,则调用rootDirResource.createRelative方法创建一个Resource,将新创建的Resource添加入结果集中。
doFindPathMatchingFileResources()实现:
1. 获取要查找资源的根路径(根路径全名)
2. 递归获得根路径下的所有资源,使用PathMatcher匹配,如果匹配成功,则创建FileSystemResource,并将其加入到结果集中。在递归进入一个目录前首先调用PathMatcher.matchStart()方法,以先简单的判断是否需要递归进去,以提升性能。
protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set result) throws IOException {
if (logger.isDebugEnabled()) {
logger.debug("Searching directory [" + dir.getAbsolutePath() +
"] for files matching pattern [" + fullPattern + "]");
}
File[] dirContents = dir.listFiles();
if (dirContents == null) {
throw new IOException("Could not retrieve contents of directory [" + dir.getAbsolutePath() + "]");
}
for (int i = 0; i < dirContents.length; i++) {
File content = dirContents[i];
String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/"