Spring源码含有通配符路径解析一.docx
- 文档编号:7297299
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:15
- 大小:22.79KB
Spring源码含有通配符路径解析一.docx
《Spring源码含有通配符路径解析一.docx》由会员分享,可在线阅读,更多相关《Spring源码含有通配符路径解析一.docx(15页珍藏版)》请在冰豆网上搜索。
Spring源码含有通配符路径解析一
如果路径包含通配符(?
*,**)spring是怎么处理的?
如果是以classpath*开头的又是如何呢?
先测试分析包含通配符(?
)的。
1./**
2. * 测试包含通配符:
*,?
的路径
3. *
D:
\\workspace-home\\spring-custom\\src\\main\\resources\\spring\\ap?
-context.xml
4. * 通过读取配置文件失败的情况,因为此时Spring不支持\\路径的通配符解析
5. *
6. * @author lihzh
7. * @date 2012-5-5 上午10:
53:
53
8. */
9.@Test
10.public void testAntStylePathFail() {
11. String pathOne = "D:
\\workspace-home\\spring-custom\\src\\main\\resources\\spring\\ap?
-context.xml";
12. ApplicationContext appContext = new FileSystemXmlApplicationContext(pathOne);
13. assertNotNull(appContext);
14. VeryCommonBean bean = null;
15. try {
16. bean = appContext.getBean(VeryCommonBean.class);
17. fail("Should not find the [VeryCommonBean].");
18. } catch (NoSuchBeanDefinitionException e) {
19. }
20. assertNull(bean);
21.}
正如测试用例所写,实际是找不到该Bean的。
这又是为什么?
Spring不是支持通配符吗?
FileSystemXmlApplicationContext的注释里也提到了通配符的情况:
1.*
The config location defaults can be overridden via {@link #getConfigLocations},
2.* Config locations can either denote concrete files like "/myfiles/context.xml"
3.* or Ant-style patterns like "/myfiles/*-context.xml" (see the
4.* {@link org.springframework.util.AntPathMatcher} javadoc for pattern details).
从代码中寻找答案。
回到上回的else分支中,因为包含通配符,所以进入第一个子分支。
1./**
2. * Find all resources that match the given location pattern via the
3. * Ant-style PathMatcher. Supports resources in jar files and zip files
4. * and in the file system.
5. * @param locationPattern the location pattern to match
6. * @return the result as Resource array
7. * @throws IOException in case of I/O errors
8. * @see #doFindPathMatchingJarResources
9. * @see #doFindPathMatchingFileResources
10. * @see org.springframework.util.PathMatcher
11. */
12. protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
13. String rootDirPath = determineRootDir(locationPattern);
14. String subPattern = locationPattern.substring(rootDirPath.length());
15. Resource[] rootDirResources = getResources(rootDirPath);
16. Set
17. for (Resource rootDirResource :
rootDirResources) {
18. rootDirResource = resolveRootDirResource(rootDirResource);
19. if (isJarResource(rootDirResource)) {
20. result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
21. }
22. else if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
23. result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));
24. }
25. else {
26. result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
27. }
28. }
29. if (logger.isDebugEnabled()) {
30. logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
31. }
32. return result.toArray(new Resource[result.size()]);
33. }
此方法传入的完整的没有处理的路径,从第一行开始,就开始分步处理解析传入的路径,首先是决定“根”路径:
determineRootDir(locationPattern)
1./**
2. * Determine the root directory for the given location.
3. *
Used for determining the starting point for file matching,
4. * resolving the root directory location to a java.io.File
5. * and passing it into retrieveMatchingFiles
, with the
6. * remainder of the location as pattern.
7. *
Will return "/WEB-INF/" for the pattern "/WEB-INF/*.xml",
8. * for example.
9. * @param location the location to check
10. * @return the part of the location that denotes the root directory
11. * @see #retrieveMatchingFiles
12. */
13. protected String determineRootDir(String location) {
14. int prefixEnd = location.indexOf(":
") + 1;
15. int rootDirEnd = location.length();
16. while (rootDirEnd > prefixEnd && getPathMatcher().isPattern(location.substring(prefixEnd, rootDirEnd))) {
17. rootDirEnd = location.lastIndexOf('/', rootDirEnd - 2) + 1;
18. }
19. if (rootDirEnd == 0) {
20. rootDirEnd = prefixEnd;
21. }
22. return location.substring(0, rootDirEnd);
23. }
这个“根”,就是不包含通配符的最长的部分,以我们的路径为例,这个“根”本来应该是:
D:
\\workspace-home\\spring-custom\\src\\main\\resources\\spring\\ ,但是实际上,从determineRootDir的实现可以看出:
首先,先找到冒号:
索引位,赋值给prefixEnd 。
然后,在从冒号开始到最后的字符串中,循环判断是否包含通配符,如果包含,则截断最后一个由"/"分割的部分,例如:
在我们路径中,就是最后的ap?
-context.xml这一段。
再循环判断剩下的部分,直到剩下的路径中都不包含通配符。
如果查找完成后,rootDirEnd=0了,则将之前赋值的prefixEnd的值赋给rootDirEnd,也就是":
"所在的索引位。
最后,将字符串从开始截断rootDirEnd。
我们的问题,就出在关键的第二步,Spring这里只在字符串中查找"/",并没有支持"\\"这样的路径分割方式,所以,自然找不到"\\",rootDirEnd=-1+1=0。
所以循环后,阶段出来的路径就是D:
,自然Spring会找不到配置文件,容器无法初始化。
基于以上分析,我们将路径修改为:
D:
/workspace-home/spring-custom/src/main/resources/spring/ap?
-context.xml,
测试通过。
刚才仅仅分析了,我们之前路径的问题所在,还有一点我想也是大家关心的,就是通配符是怎么匹配的呢?
那我们就继续分析源码,回到findPathMatchingResources 方法。
将路径分成包含通配符和不包含的两部分后,Spring会将根路径生成一个Resource,用的还是getResources方法。
然后检查根路径的类型,是否是Jar路径?
是否是VFS路径?
对于我们这种普通路径,自然走到最后的分支。
1./**
2. * Find all resources in the file system that match the given location pattern
3. * via the Ant-style PathMatcher.
4. * @param rootDirResource the root directory as Resource
5. * @param subPattern the sub pattern to match (below the root directory)
6. * @return the Set of matching Resource instances
7. * @throws IOException in case of I/O errors
8. * @see #retrieveMatchingFiles
9. * @see org.springframework.util.PathMatcher
10. */
11. protected Set
12. throws IOException {
13.
14. File rootDir;
15. try {
16. rootDir = rootDirResource.getFile().getAbsoluteFile();
17. }
18. catch (IOException ex) {
19. if (logger.isWarnEnabled()) {
20. logger.warn("Cannot search for matching files underneath " + rootDirResource +
21. " because it does not correspond to a directory in the file system", ex);
22. }
23. return Collections.emptySet();
24. }
25. return doFindMatchingFileSystemResources(rootDir, subPattern);
26. }
1./**
2. * Retrieve files that match the given path pattern,
3. * checking the given directory and its subdirectories.
4. * @param rootDir the directory to start from
5. * @param pattern the pattern to match against,
6. * relative to the root directory
7. * @return the Set of matching File instances
8. * @throws IOException if directory contents could not be retrieved
9. */
10. protected Set
11. if (!
rootDir.exists()) {
12. // Silently skip non-existing directories.
13. if (logger.isDebugEnabled()) {
14. logger.debug("Skipping [" + rootDir.getAbsolutePath() + "] because it does not exist");
15. }
16. return Collections.emptySet();
17. }
18. if (!
rootDir.isDirectory()) {
19. // Complain louder if it exists but is no directory.
20. if (logger.isWarnEnabled()) {
21. logger.warn("Skipping [" + rootDir.getAbsolutePath() + "] because it does not denote a directory");
22. }
23. return Collections.emptySet();
24. }
25. if (!
rootDir.canRead()) {
26. if (logger.isWarnEnabled()) {
27. logger.warn("Cannot search for matching files underneath directory [" + rootDir.getAbsolutePath() +
28. "] because the application is not allowed to read the directory");
29. }
30. return Collections.emptySet();
31. }
32. String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, "/");
33. if (!
pattern.startsWith("/")) {
34. fullPattern += "/";
35. }
36. fullPattern = fullPattern + StringUtils.replace(pattern, File.separator, "/");
37. Set
38. doRetrieveMatchingFiles(fullPattern, rootDir, result);
39. return result;
40. }
1./**
2. * Recursively retrieve files that match the given pattern,
3. * adding them to the given result list.
4. * @param fullPattern the pattern to match against,
5. * with prepended root directory path
6. * @param dir the current directory
7. * @param result the Set of matching File instances to add to
8. * @throws IOException if directory contents could not be retrieved
9. */
10. protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set
11. if (logger.isDebugEnabled()) {
12. logger.debug("Searching directory [" + dir.getAbsolutePath() +
13. "] for files matching pattern [" + fullPattern + "]");
14. }
15. File[] dirContents = dir.listFiles();
16. if (dirContents == null) {
17. if (logger.isWarnEnabled()) {
18. logger.warn("Could not retrieve contents of directory [" + dir.getAbsolutePath() + "]");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring 源码 含有 通配符 路径 解析