Ant 风格路径匹配

Ant 风格源自 Apache Ant(一个 Java 构建工具)的路径通配符匹配模式,后被 Spring、Maven、Gradle 等广泛采用,成为 Java 生态中路径匹配的事实标准。

通配符规则

符号含义
?匹配文件名或目录名中的单个字符
*匹配文件名或目录名中的零个或多个字符(不跨越目录层级)
**匹配零层或多层目录(跨越目录层级)

具体示例

假设目录结构:

src/
├── main/
│   ├── java/
│   │   └── com/demo/
│   │       ├── UserController.java
│   │       ├── UserService.java
│   │       └── UserMapper.java
│   └── resources/
│       └── application.yml
└── test/
    └── java/com/demo/
        └── UserServiceTest.java
模式匹配结果
**/*.java所有层级的 .java 文件
src/main/**/*.javamain 下的 Java 文件
**/*Service*.java含 “Service” 的文件
src/main/java/com/demo/User*.java该目录下 User 开头的文件
src/**/demo/*.javademo 目录下直接子文件

三个核心区别

*    不跨层    —  仅匹配当前目录层级下的文件名/目录名
**   跨层      —  可以跨越任意多级子目录
?    单字符    —  精确匹配一个字符
"com/**/*.java"    // 匹配 com/ 及所有子目录下的 .java 文件
"com/*/*.java"     // 只匹配 com/ 下正好一层子目录里的 .java 文件
"com/*/Test?.java" // 匹配 com/下一层中名为 TestX.java 的文件(X为单字符)

与正则表达式的对比

概念Ant 风格正则表达式
任意字符(不跨 /*[^/]*
任意字符(跨 /**.*
单个字符?.

Ant 风格更直观,无需反斜杠转义,专门适合描述文件系统路径。

Spring 中的应用

// classpath*: 扫描所有模块
String scanPath = "classpath*:" + applicationName + "/dictionary/*.json";
Resource[] resources = resolver.getResources(scanPath);
 
// classpath: 仅扫描第一个匹配的 classpath 根
Resource[] resources = resolver.getResources("classpath:META-INF/spring.factories");

参考链接