`

spring如何解析通配符路径

 
阅读更多

转自: http://goodscript.iteye.com/blog/1161519

在spring的配置文件中、经常看见类似这样的配置路径: 

Java代码  收藏代码
  1. classpath:/com/module/**/*sql.xml  


系统会根据配置路径自动加载符合路径规则的xml文件 
假如让你实现这样的功能: 
根据一个通配符路径加载符合规则的xml文件你会怎么做? 

先看一个小例子: 

Java代码  收藏代码
  1. import java.io.IOException;  
  2.   
  3. import org.springframework.core.io.Resource;  
  4. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;  
  5. import org.springframework.core.io.support.ResourcePatternResolver;  
  6.   
  7. public class XMLManager {  
  8.   
  9.     private String location = "classpath:*.xml";  
  10.   
  11.     public void readFile() throws IOException {  
  12.         ResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();  
  13.         Resource[] source = resourceLoader.getResources(location);  
  14.         for (int i = 0; i < source.length; i++) {  
  15.             Resource resource = source[i];  
  16.             System.out.println(resource.getFilename());  
  17.   
  18.         }  
  19.     }  
  20.   
  21.     public static void main(String[] args) {  
  22.   
  23.         XMLManager m = new XMLManager();  
  24.         try {  
  25.             m.readFile();  
  26.         } catch (IOException e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.     }  
  30. }  



输出结果: 

Java代码  收藏代码
  1. applicationContext.xml  
  2. logback.xml  
  3. menu_my.xml  


是不是很简单? 
只要调用PathMatchingResourcePatternResolver的getResources方法就可以实现我们想要的功能。 
下面深入研究一下spring的源码PathMatchingResourcePatternResolver: 
1、getResources方法 

Java代码  收藏代码
  1. public Resource[] getResources(String locationPattern) throws IOException {  
  2.         Assert.notNull(locationPattern, "Location pattern must not be null");  
  3.         if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {  
  4.             // a class path resource (multiple resources for same name possible)  
  5.             if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {  
  6.                 // a class path resource pattern  
  7.                 return findPathMatchingResources(locationPattern);  
  8.             }  
  9.             else {  
  10.                 // all class path resources with the given name  
  11.                 return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));  
  12.             }  
  13.         }  
  14.         else {  
  15.             // Only look for a pattern after a prefix here  
  16.             // (to not get fooled by a pattern symbol in a strange prefix).  
  17.             int prefixEnd = locationPattern.indexOf(":") + 1;  
  18.             if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {  
  19.                 // a file pattern  
  20.                 return findPathMatchingResources(locationPattern);  
  21.             }  
  22.             else {  
  23.                 // a single resource with the given name  
  24.                 return new Resource[] {getResourceLoader().getResource(locationPattern)};  
  25.             }  
  26.         }  
  27.     }  


该方法主要是判断locationPattern是否包含有通配符、如果包含通配符则调用findPathMatchingResources方法、没有包含通配符就不需要解析了 
2、findPathMatchingResources方法 

Java代码  收藏代码
  1. protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {  
  2.     String rootDirPath = determineRootDir(locationPattern);  
  3.     String subPattern = locationPattern.substring(rootDirPath.length());  
  4.     Resource[] rootDirResources = getResources(rootDirPath);  
  5.     Set<Resource> result = new LinkedHashSet<Resource>(16);  
  6.     for (Resource rootDirResource : rootDirResources) {  
  7.         rootDirResource = resolveRootDirResource(rootDirResource);  
  8.         if (isJarResource(rootDirResource)) {  
  9.             result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));  
  10.         }  
  11.         else if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {  
  12.             result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));  
  13.         }  
  14.         else {  
  15.             result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));  
  16.         }  
  17.     }  
  18.     if (logger.isDebugEnabled()) {  
  19.         logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);  
  20.     }  
  21.     return result.toArray(new Resource[result.size()]);  
  22. }  


把locationPattern拆分成两部分:rootDirPath 和subPattern 
rootDirPath是根目录路径 
subPattern是子目录路径匹配规则字符串 
历遍根目录下的所有子目录、并得到所有的子目录 
在doFindPathMatchingFileResources(rootDirResource, subPattern)方法中 
再根据子目录逐个逐个去匹配subPattern 
3、doFindPathMatchingFileResources 

Java代码  收藏代码
  1. protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)  
  2.         throws IOException {  
  3.   
  4.     File rootDir;  
  5.     try {  
  6.         rootDir = rootDirResource.getFile().getAbsoluteFile();  
  7.     }  
  8.     catch (IOException ex) {  
  9.         if (logger.isWarnEnabled()) {  
  10.             logger.warn("Cannot search for matching files underneath " + rootDirResource +  
  11.                     " because it does not correspond to a directory in the file system", ex);  
  12.         }  
  13.         return Collections.emptySet();  
  14.     }  
  15.     return doFindMatchingFileSystemResources(rootDir, subPattern);  
  16. }  


跳转到另一个方法doFindMatchingFileSystemResources: 

Java代码  收藏代码
  1. protected Set<Resource> doFindMatchingFileSystemResources(File rootDir, String subPattern) throws IOException {  
  2.     if (logger.isDebugEnabled()) {  
  3.         logger.debug("Looking for matching resources in directory tree [" + rootDir.getPath() + "]");  
  4.     }  
  5.     Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);  
  6.     Set<Resource> result = new LinkedHashSet<Resource>(matchingFiles.size());  
  7.     for (File file : matchingFiles) {  
  8.         result.add(new FileSystemResource(file));  
  9.     }  
  10.     return result;  
  11. }  


retrieveMatchingFiles 

Java代码  收藏代码
  1. protected Set<File> retrieveMatchingFiles(File rootDir, String pattern) throws IOException {  
  2.     if (!rootDir.exists()) {  
  3.         // Silently skip non-existing directories.  
  4.         if (logger.isDebugEnabled()) {  
  5.             logger.debug("Skipping [" + rootDir.getAbsolutePath() + "] because it does not exist");  
  6.         }  
  7.         return Collections.emptySet();  
  8.     }  
  9.     if (!rootDir.isDirectory()) {  
  10.         // Complain louder if it exists but is no directory.  
  11.         if (logger.isWarnEnabled()) {  
  12.             logger.warn("Skipping [" + rootDir.getAbsolutePath() + "] because it does not denote a directory");  
  13.         }  
  14.         return Collections.emptySet();  
  15.     }  
  16.     if (!rootDir.canRead()) {  
  17.         if (logger.isWarnEnabled()) {  
  18.             logger.warn("Cannot search for matching files underneath directory [" + rootDir.getAbsolutePath() +  
  19.                     "] because the application is not allowed to read the directory");  
  20.         }  
  21.         return Collections.emptySet();  
  22.     }  
  23.     String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, "/");  
  24.     if (!pattern.startsWith("/")) {  
  25.         fullPattern += "/";  
  26.     }  
  27.     fullPattern = fullPattern + StringUtils.replace(pattern, File.separator, "/");  
  28.     Set<File> result = new LinkedHashSet<File>(8);  
  29.     doRetrieveMatchingFiles(fullPattern, rootDir, result);  
  30.     return result;  
  31. }  


调用递归方法: 
doRetrieveMatchingFiles 

Java代码  收藏代码
  1. protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set<File> result) throws IOException {  
  2.     if (logger.isDebugEnabled()) {  
  3.         logger.debug("Searching directory [" + dir.getAbsolutePath() +  
  4.                 "] for files matching pattern [" + fullPattern + "]");  
  5.     }  
  6.     File[] dirContents = dir.listFiles();  
  7.     if (dirContents == null) {  
  8.         if (logger.isWarnEnabled()) {  
  9.             logger.warn("Could not retrieve contents of directory [" + dir.getAbsolutePath() + "]");  
  10.         }  
  11.         return;  
  12.     }  
  13.     for (File content : dirContents) {  
  14.         String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/");  
  15.         if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) {  
  16.             if (!content.canRead()) {  
  17.                 if (logger.isDebugEnabled()) {  
  18.                     logger.debug("Skipping subdirectory [" + dir.getAbsolutePath() +  
  19.                             "] because the application is not allowed to read the directory");  
  20.                 }  
  21.             }  
  22.             else {  
  23.                 doRetrieveMatchingFiles(fullPattern, content, result);  
  24.             }  
  25.         }  
  26.         if (getPathMatcher().match(fullPattern, currPath)) {  
  27.             result.add(content);  
  28.         }  
  29.     }  
  30. }  
分享到:
评论

相关推荐

    Spring源码含有通配符路径解析一[文].pdf

    Spring源码含有通配符路径解析一[文].pdf

    跟我学spring3(1-7)

    【第四章】 资源 之 4.4 Resource通配符路径 ——跟我学spring3 【第五章】Spring表达式语言 之 5.1 概述 5.2 SpEL基础 ——跟我学spring3 【第五章】Spring表达式语言 之 5.3 SpEL语法 ——跟我学spring3 【第五章...

    跟我学spring3(1-7).pdf

    Spring概述2.1 IoC基础2.2 IoC 容器基本原理2.3 IoC的配置使用——跟我学Spring33.1 DI的配置使用3.2 循环依赖3.3 更多DI的知识 3.4 Bean的作用域 4.1 基础知识4.2 内置Resource实现4.3 访问Resource4.4 Resource...

    跟开涛学Spring

    1.14 【第四章】 资源 之 4.4 Resource通配符路径 ——跟我学spring3 . . . . . . . . . . . . . . . . . . . . . . . .171 1.15 【第五章】Spring表达式语言 之 5.1 概述 5.2 SpEL基础 ——跟我学spring3 . . . . ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    4.7.2. Application context构造器中资源路径的通配符 4.7.2.1. Ant风格的pattern 4.7.2.2. classpath*: 前缀 4.7.2.3. 其他关于通配符的说明 4.7.3. FileSystemResource 提示 5. 校验,数据绑定,BeanWrapper,与...

    Spring 2.0 开发参考手册

    4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 提示 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到...

    Spring中文帮助文档

    4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 说明 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到...

    spring chm文档

    4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 提示 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到...

    Spring API

    4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 说明 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到...

    ssh(structs,spring,hibernate)框架中的上传下载

    Struts+Spring+Hibernate实现上传下载    本文将围绕SSH文件上传下载的主题,向您详细讲述如何开发基于SSH的Web程序。SSH各框架的均为当前最新版本:  •Struts 1.2  •Spring 1.2.5  •Hibernate 3.0  本文...

    maven相关资料

    或者用通配符: ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/*.xml"); 二、ClassPathXmlApplicationContext[只能读放在web-info/classes目录下的配置文件]和...

    java项目源码之UrlRewriter Java v2.0 RC1-urlrewriterjava.rar

    基于 Servlet Filter 或者 Spring Interceptor 等技术,实现对请求的拦截和处理。 在请求到达服务器之前或者返回给客户端之前,通过拦截器对 URL 进行重写操作。 灵活的重写规则: 提供灵活的 URL 重写规则配置,...

    java命名规范 开发规范

    1. Action建议统一遵守通配符的约定,basePath/web/moduleName/*_ *.action {1}  EntityName,{2}  ActionMethodName 2. 统一命名规则:接口类似UserService,接口实现类型UserServiceImpl;(IUserService和...

    java微信公众号MVC开发框架

    url-pattern模式匹配微信公众号平台服务器配置的URL配置,如果需要处理多个微信公众号,可以配置多个servlet-mapping或者使用路径通配符匹配多个url链接。 3、spring配置文件 spring配置文件applicationContext.xml...

    Struts2 in action中文版

    15.2.1 通配符方法的选择 310 15.2.2 动态工作流 312 15.3 使用令牌防止表单重复提交 313 15.3.1 使用s:token/表单标签 313 15.3.2 令牌拦截器规则的例外 314 15.4 自动显示等待页面 316 15.5 完成CRUD操作的一个...

    javaSE代码实例

    13.6.3 利用正则式对字符串进行分析 268 13.7 小结 269 第14章 集合框架——强大的对象管理器 270 14.1 Object类——所有类的超类 270 14.1.1 toString方法的重写 270 14.1.2 equals方法的意义 271 ...

Global site tag (gtag.js) - Google Analytics