文章目录

  • PathMatcher接口
    • 使用场景
    • 接口方法
  • AntPathMatcher类
    • 匹配规则
    • 主要方法
      • 1. isPattern
      • 2. match
      • 3. matchStart
      • 4. extractPathWithinPattern
      • 5. extractUriTemplateVariables
      • 6. getPatternComparator
      • 7. combine

PathMatcher接口

Spring的PathMatcher路径匹配器接口,用于支持带通配符的资源路径匹配。

使用场景

PathMatcher接口在Spring的许多场景下使用,比如:

  • PathMatchingResourcePatternResolver:资源扫描,启动时扫描并加载资源
  • AbstractUrlHandlerMapping:请求路径映射到 Controller
  • WebContentInterceptor:拦截器拦截路径分析

接口方法

方法 描述
boolean isPattern(String path) 判断路径是否是模式
boolean match(String pattern, String path) 判断路径是否完全匹配
boolean matchStart(String pattern, String path) 判断路径是否前缀匹配
前缀匹配的意思:路径能与模式的前面部分匹配,但模式可能还有后面多余部分
例如:/test能前缀匹配/test/{id}(但模式还有多余的/{id}部分未匹配)
String extractPathWithinPattern(String pattern, String path) 得到模式匹配的部分值
该方法只返回路径的实际模式匹配部分
例如:myroot/*.html 匹配 myroot/myfile.html 路径,结果为 myfile.html
Map<String, String> extractUriTemplateVariables(String pattern, String path) 提取路径中的路径参数值
Comparator<String> getPatternComparator(String path) 得到一个排序比较器,用于对匹配到的所有路径进行排序
String combine(String pattern1, String pattern2) 合并两个模式

AntPathMatcher类

AntPathMatcher是Spring为PathMatcher接口提供的默认实现,支持Ant风格的路径匹配。

匹配规则

AntPathMatcher支持的匹配规则:

规则 描述
? 匹配一个字符
* 在一个路径段中匹配零个、一个或多个字符
** 匹配零个或多个路径段,直到路径结束
{id} 匹配一个路径段,并将该路径段的值作为变量id的变量值
{id:[a-z]+} 匹配一个满足正则([a-z]+)路径段,并将该路径段的值作为变量id的变量值

举例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();// ?System.out.println(matcher.match("/test/a?c", "/test/abc"));// true// *System.out.println(matcher.match("/test/*", "/test/"));// trueSystem.out.println(matcher.match("/test/*", "/test/aa"));// trueSystem.out.println(matcher.match("/test/*.html", "/test/aa"));// false// **System.out.println(matcher.match("/test/**", "/test/"));// trueSystem.out.println(matcher.match("/test/**", "/test/aa"));// trueSystem.out.println(matcher.match("/test/**", "/test/aa/bb"));// true// {id}System.out.println(matcher.match("/test/{id}", "/test/111"));// trueSystem.out.println(matcher.match("/test/a{id}", "/test/a111"));// trueSystem.out.println(matcher.match("/test/{id}/aa", "/test/111/aa"));// trueSystem.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-haha/aa"));// true// {id:[a-z]+}System.out.println(matcher.match("/test/{id:[a-z]+}", "/test/111"));// falseSystem.out.println(matcher.match("/test/{id:[a-z]+}", "/test/abc"));// trueSystem.out.println(matcher.match("/test/{id:\\w+}", "/test/1a_"));// trueSystem.out.println(matcher.match("/test/{id:\\w+}", "/test/--"));// false}

一些不匹配情况原因:

模式 路径 原因
/user/aaa/ /user/aaa 结束符不一致
/user/*/ /user/aaa 结束符不一致

实际在Spring项目中使用的时候,你会发现:就算实际请求的结束符为/,但还是能匹配成功。这又是为什么呢?

两个关键属性:

  • useSuffixPatternMatch:设置是否使用后缀模式匹配,如“/user”是否匹配/user.*,默认是

    这种模式下,实际请求.后面加任何后缀,都会匹配到。如:实际请求“/user.html”能匹配上“/user”。

  • useTrailingSlashMatch:设置是否使用后缀路径模式匹配,如“/user”是否匹配“/user/”,默认是

    这种模式下,实际请求加、后缀,都会匹配到。如:实际请求“/user/”能匹配上“/user”。

如何修改useSuffixPatternMatch、useTrailingSlashMatch属性的值,可参考文章:https://blog.csdn.net/m0_56069948/article/details/124791784

关键源码:

PatternsRequestCondition类的getMatchingPattern方法

 private String getMatchingPattern(String pattern, String lookupPath) {// 模式与路径相等,直接返回模式if (pattern.equals(lookupPath)) {return pattern;}// 如果使用后缀模式匹配,返回的模式会拼接上合适的后缀,如.htmlif (this.useSuffixPatternMatch) {if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) {for (String extension : this.fileExtensions) {if (this.pathMatcher.match(pattern + extension, lookupPath)) {return pattern + extension;}}}else {boolean hasSuffix = pattern.indexOf('.') != -1;if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {return pattern + ".*";}}}if (this.pathMatcher.match(pattern, lookupPath)) {return pattern;}// 如果使用后缀路径模式匹配,返回的模式会拼接上/if (this.useTrailingSlashMatch) {if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {return pattern + "/";}}return null;}

因此,getMatchingPattern方法返回的模式再与请求路径进行模式匹配当然能匹配上了。

主要方法

1. isPattern

判断路径是否是模式。

只要路径中拥有 *?{},则就是模式。

public boolean isPattern(@Nullable String path) {if (path == null) {return false;}boolean uriVar = false;for (int i = 0; i < path.length(); i++) {char c = path.charAt(i);if (c == '*' || c == '?') {return true;}if (c == '{') {uriVar = true;continue;}if (c == '}' && uriVar) {return true;}}return false;
}

示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.isPattern("/test/{id}"));// true}

2. match

判断路径是否完全匹配

public boolean match(String pattern, String path) {return doMatch(pattern, path, true, null);
}

示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.match("/test/*", "/test/111"));// trueSystem.out.println(matcher.match("/test/**", "/test/111/222"));// trueSystem.out.println(matcher.match("/test/{id}", "/test/111"));// trueSystem.out.println(matcher.match("/test/{id}/aa", "/test/111/aa"));// trueSystem.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-haha/aa"));// trueSystem.out.println(matcher.match("/test/{id}-{name}/aa", "/test/111-/aa"));// true}

3. matchStart

判断路径是否前缀匹配

前缀匹配的意思:路径能与模式的前面部分匹配,但模式可能还有后面多余部分(可以理解为模式是否是以路径开头)

public boolean matchStart(String pattern, String path) {return doMatch(pattern, path, false, null);
}

示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.matchStart("/test/*", "/test"));// trueSystem.out.println(matcher.matchStart("/test/aa/*", "/test"));// trueSystem.out.println(matcher.matchStart("/test/{id}", "/test"));// trueSystem.out.println(matcher.matchStart("/test/{id}-{name}/aa", "/test"));// trueSystem.out.println(matcher.matchStart("/test/{id}", "/test/111/222"));// false}

4. extractPathWithinPattern

得到模式匹配的映射部分。找出通过*或者?匹配上的那一段路径及其后续路径。

示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.extractPathWithinPattern("/test/*", "/test"));//System.out.println(matcher.extractPathWithinPattern("/test/*", "/test/aa"));// aaSystem.out.println(matcher.extractPathWithinPattern("/test/**", "/test/aa/bb"));// aa/bbSystem.out.println(matcher.extractPathWithinPattern("/test/a?c/aa", "/test/abc/aa"));// abc/aaSystem.out.println(matcher.extractPathWithinPattern("/test/aa?c/aa/cc", "/test/abc/aa"));// abc/aa}

5. extractUriTemplateVariables

路径必须完全匹配(否则抛出异常),并提取路径中的路径参数值。

示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.extractUriTemplateVariables("/test/{id}", "/test/111"));// {id=111}System.out.println(matcher.extractUriTemplateVariables("/test/a{id}", "/test/a111"));// {id=111}System.out.println(matcher.extractUriTemplateVariables("/test/{id}/aa", "/test/111/aa"));// {id=111}System.out.println(matcher.extractUriTemplateVariables("/test/{id}-{name}/aa", "/test/111-haha/aa"));// {id=111, name=haha}System.out.println(matcher.extractUriTemplateVariables("/test/{id:[a-z]+}", "/test/abc"));// {id=abc}System.out.println(matcher.extractUriTemplateVariables("/test/{id:\\w+}", "/test/1a_"));// {id=1a_}}

6. getPatternComparator

得到一个排序比较器。

 public Comparator<String> getPatternComparator(String path) {return new AntPatternComparator(path);}

7. combine

合并两个模式。
示例:

    public static void main(String[] args) {AntPathMatcher matcher = new AntPathMatcher();System.out.println(matcher.combine("/test/*", "/test/aa"));// /test/aaSystem.out.println(matcher.combine("/test/*", "/test/aa/bb"));// /test/test/aa/bbSystem.out.println(matcher.combine("/test/**", "/test/aa"));// /test/aaSystem.out.println(matcher.combine("/test/{id}", "/test/aa"));// /test/{id}/test/aa}

参考文章:
https://blog.csdn.net/gongm24/article/details/124961800

Spring路径匹配器AntPathMatcher相关推荐

  1. AntPathMatcher路径匹配器

    有志者,事竟成 文章持续更新,可以关注[小奇JAVA面试]第一时间阅读,回复[资料]获取福利,回复[项目]获取项目源码,回复[简历模板]获取简历模板,回复[学习路线图]获取学习路线图. 文章目录 一. ...

  2. PathMatcher 路径匹配器

    1. 参考链接:https://blog.csdn.net/andy_zhang2007/article/details/88884286 package org.springframework.ut ...

  3. 过滤器匹配符包含单词_Hamcrest包含匹配器

    过滤器匹配符包含单词 与Hamcrest 1.2相比 ,针对Matchers类的Hamcrest 1.3 Javadoc文档为该类的几种方法添加了更多文档. 例如,四个重载的contains方法具有更 ...

  4. 【图像配准】多图配准/不同特征提取算法/匹配器比较测试

    前言 本文首先完成之前专栏前置博文未完成的多图配准拼接任务,其次对不同特征提取器/匹配器效率进行进一步实验探究. 各类算法原理简述 看到有博文[1]指出,在速度方面SIFT<SURF<BR ...

  5. spaCy V3.0 基于规则匹配(2)----高效的短语匹配器和依存句法匹配器

    1 短语匹配器(PhraseMatcher) 1.1 基本用法 对于需要匹配大型术语列表的情况,可以通过PhraseMatcher和创建Doc对象来代替词符匹配模式(token patterns),可 ...

  6. Jest 测试框架 expect 和 匹配器 matcher 的设计原理解析

    副标题:SAP Spartacus SSR 优化的单元测试分析之二 - 调用参数检测 源代码: it(`should pass parameters to the original engine in ...

  7. Mockito匹配器优先

    这篇文章是意见. 让我们看一下Mockito中用于在Java中进行测试的verify方法. 示例: verify(myMock).someFunction(123) –期望在模拟ONCE上使用输入12 ...

  8. Hamcrest匹配器常用方法总结

    一.Hamcrest是什么? Hamcrest is a library of matchers, which can be combined in to create flexible expres ...

  9. SLAM Cartographer(13)基于Ceres库的扫描匹配器

    SLAM Cartographer(13)基于Ceres库的扫描匹配器 1. 扫描匹配器 2. 残差计算 2.1. 平移残差 2.2. 角度残差 2.3. 占据空间残差 1. 扫描匹配器 通过< ...

最新文章

  1. LabVIEW图像灰度分析与变换(基础篇—4)
  2. SAP MM 采购价格里的阶梯价格
  3. STM32 KEIL MDK 本地时间和Unix timestamp相互转换
  4. Spring AOP(一):概览
  5. 新iPhone又被各个品牌玩坏了,这里的人个个都是人才,说话又好听…
  6. idea重写接口没有@override_接口和抽象有什么区别?
  7. 在前台或会员中心获取表单向导里提交的数据
  8. 惠普电脑按F12锁屏如何解?
  9. 熬夜不易,请老范喝杯烈酒
  10. 【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)
  11. 产品策划流程体系、工具
  12. 基于web的模型管理系统的设计
  13. 【Python】关于DataFrame数据类型二三事
  14. 米的换算单位和公式_一米等于多少分米(常见的长度单位换算公式方法)
  15. springboot+Zuul网关服务
  16. Java小游戏-幸运抽奖-进阶版(可多抽取多次)
  17. 【区块链新手快速入门】如何构建一个区块链
  18. 读书笔记-《赢在用户:Web人物角色创建和应用实践指南》
  19. LeetCode 112 路径总和 python3
  20. Python之简单飞机行李托运计费系统

热门文章

  1. 创建SharePoint 2010 Timer Job
  2. 中国移动手机定位lbs接口协议讲解及java代码实现_Lbs定位功能的实现
  3. 计算机技术未来发展趋势
  4. Android 源码编译问题总结
  5. Json的数据结构详解
  6. ssm宾馆管理信息系统jjf0x【独家源码】 应对计算机毕业设计困难的解决方案
  7. 华为杯2022研究生数学建模赛题+解压码
  8. json特殊字符串处理
  9. 【最新消息】这款商业级仓储管理系统项目ModernWMS宣布开源了
  10. 一千万数据,怎么快速查询?