重学SpringBoot3-路径匹配机制
- AntPathMatcher
- PathPatternParser 和 PathPattern
- 演示
- AntPathMatcher 示例
- PathPattern 示例
- 性能和精确度的提升
- 选择使用哪一种
在 Spring Framework 5.3 及 Spring Boot 2.4 之后,引入了一种新的路径匹配机制,这一变化在 Spring Boot 3 中得到了保留和进一步的应用。这个新机制主要是通过 PathPattern
代替了传统的 AntPathMatcher
。AntPathMatcher
是基于 Ant 风格的路径匹配,而 PathPattern
则是一个更高效、更精确的路径匹配方式,它是通过 PathPatternParser
解析得到的。
AntPathMatcher
-
定义:
AntPathMatcher
是 Spring 框架中一个基于 Ant 风格模式的路径匹配器,它支持使用?
、*
和**
等通配符进行匹配。- *:表示任意数量的字符。
- ?:表示任意一个字符。
- :表示任意数量的目录**。
- {}:表示一个命名的模式占位符。
- []:表示字符集合,例如[a-z]表示小写字母。
-
用途: 主要用于 URL 模式匹配,比如在 Spring MVC 中定义
@RequestMapping
时就可以使用Ant风格的路径。 -
特点: 灵活但在性能上可能不如
PathPattern
,尤其是在复杂模式匹配时。
PathPatternParser 和 PathPattern
PathPatternParser
: 一个新的路径解析器,用于解析路径模式字符串,创建PathPattern
对象。它引入了更严格的语法规则,并且设计了更高效的匹配算法。- PathPattern: 由
PathPatternParser
解析路径模式字符串得到的对象,代表了一种更加精确和高效的路径匹配方式。 - 特点:
- 性能: 相比
AntPathMatcher
,PathPattern
提供了更高的性能。这是因为PathPattern
在匹配过程中采用了更加高效的算法,在 jmh 基准测试下,有 6~8 倍吞吐量提升,降低 30%~40%空间分配率。 - 精确性:
PathPattern
的语法规则更严格,能够提供更精确的匹配结果。 - 使用场景: 在 Spring Framework 5.3 及之后的版本中,默认使用
PathPattern
进行路径匹配。如果你的应用是基于这些版本的 Spring Boot 构建的,那么在处理路径匹配时,你将会默认使用PathPattern
。
- 性能: 相比
演示
让我们通过具体的例子来进一步理解AntPathMatcher
与PathPattern
之间的区别以及如何在实践中应用它们。
AntPathMatcher 示例
假设我们有以下的路径模式与 URL,来看看AntPathMatcher
是如何进行匹配的:
-
模式:
/spring/*/example
- URL:
/spring/boot/example
- 使用
AntPathMatcher
,这个URL与模式是匹配的,因为*
可以匹配任意的一段文本(在这个例子中是boot
)。
@Slf4j @RestController public class HelloController { @GetMapping("/spring/*/example") public String hello(HttpServletRequest request) { //获取请求路径并返回 return request.getRequestURI(); } }
- URL:
-
模式:
/spring/**/example
- URL:
/spring/boot/java/example
- 同样,这个URL与模式也是匹配的,因为
**
可以匹配任意长度的路径(在这个例子中是boot/java
)
- URL:
PathPattern 示例
PathPattern
提供了更加精细的控制以及性能优化。使用PathPatternParser
解析同样的模式,我们可以得到类似的匹配结果,但是PathPattern
在解析和匹配的过程中更加高效:
-
模式:
/a*/b?/{c:[a-z]+}
- “/a*”:表示以"/a"开头,后面可以跟任意数量的字符;
- “/b?”:表示以"/b"开头,后面可以跟任意一个的字符;
- “{c:[a-z]+}”:表示路径变量 c,其值必须是由一个或多个小写字母 a-z 组成的字符串。
- URL:
/abc/b1/ccc
@Slf4j @RestController public class HelloController { @GetMapping("/a*/b?/{c:[a-z]+}") public String hello(HttpServletRequest request, @PathVariable("c") String variable) { log.info("variable:{}", variable); //获取请求路径并返回 return request.getRequestURI(); } }
-
模式:
/spring/**/example
: "*" 多段匹配的支持仅允许在模式末尾使用*,如果要使用需要切换到 AntPathMatcher 模式。
解决办法:spring.mvc.pathmatch.matching-strategy=ant_path_matcher
性能和精确度的提升
PathPattern
的一个主要改进是在于它的匹配算法,它使用了更少的字符串比较和更加高效的数据结构。这意味着在处理大量路由和复杂模式时,PathPattern
能够提供更快的匹配速度和更低的内存占用。
此外,PathPattern
支持一些新的匹配符,例如:
{spring:[a-z]+}
: 表示路径段必须由一个或多个小写字母组成,且该段被捕获为名为spring
的变量。?
: 匹配任何单个字符{*spring}
: 贪婪匹配任意数量的字符,并将其捕获为名为spring
的变量。
选择使用哪一种
在 Spring Boot 2.4 及以上版本中,默认使用 PathPatternParser
。但是,开发者可以通过配置选择使用旧的 AntPathMatcher
。如果你的应用需要向后兼容或者依赖于 AntPathMatcher
的特定行为,你可能会选择继续使用 AntPathMatcher
。
为了切换回 AntPathMatcher
,你可以在你的 application.properties 或 application.yml 文件中设置以下属性:
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
总的来说,PathPatternParser
和PathPattern
提供了一种更现代、更高效的路径匹配方式,适用于大多数新的 Spring 应用程序。但对于那些需要与旧代码库兼容或者有特定路径匹配需求的项目,AntPathMatcher
仍然是一个可行的选择。