Spring5 里边的新玩法!这种 URL 请求让我涨见识了
bigegpt 2025-03-24 14:12 6 浏览
Spring5 也已经出来好久了,里边有一些新玩法也需要我们去慢慢揭开面纱,这不,松哥最近在研究 SpringMVC 源码的时候,就看到这样一段代码:
protected String initLookupPath(HttpServletRequest request) {
if (usesPathPatterns()) {
request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
String lookupPath = requestPath.pathWithinApplication().value();
return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
}
else {
return getUrlPathHelper().resolveAndCacheLookupPath(request);
}
}
这个方法就是 Spring5 里边出来的,以前是没有这个方法的。在旧的 SpringMVC 中,当我们需要获取当前请求地址的时候,直接通过如下方式获取:
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
但是现在变了,现在获取当前请求 URL 地址时,方式如下:
String lookupPath = initLookupPath(request);
两种方式相比,主要是 initLookupPath 方法中多了 usesPathPatterns 选项,这是 Spring5 中的新玩意,所以今天松哥就通过一篇简单的文章来和大家分享一下 usesPathPatterns 到底是什么,该怎么玩!
这可不是一个小变化哦!特别是如果你在项目中使用了 WebFlux,那么这个东西就显得尤为重要了!
AntPathMatcher
当我们使用 @RequestMapping 注解去标记请求接口的时候(或者使用它的类似方法如 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping),我们可以使用一些通配符去匹配 URL 地址,举个简单例子,假设我有下面五个接口:
@GetMapping("/hello/**/hello")
public String hello() {
return "/hello/**/hello";
}
@GetMapping("/h?llo")
public String hello2() {
return "/h?llo";
}
@GetMapping("/**/*.html")
public String hello3() {
return "/**/*.html";
}
@GetMapping("/hello/{p1}/{p2}")
public String hello4(@PathVariable String p1, @PathVariable String p2) {
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
return "/hello/{p1}/{p2}";
}
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
System.out.println("name = " + name);
System.out.println("version = " + version);
System.out.println("ext = " + ext);
}
在解释接口的含义之前,先来说说这几个通配符的含义:
通配符 含义 ** 匹配0个或者多个目录 * 匹配0个或者多个字符 ? 匹配任意单个字符
了解了通配符的含义,我们再来说说各个接口都能接收哪些请求:
- 第一个接口,可以接收诸如 /hello/123/123/hello、/hello/a/hello 以及 /hello/hello 这样的请求,因为中间的 ** 代表 0 个或者多个目录。
- 第二个接口,可以接收诸如 /hallo、/hello、/hMllo 之类的请求,注意它不能接收 /haallo 或者 /hllo,因为 ? 表示一个字符。
- 第三个接口可以接收任意以 .html 为后缀的请求,例如 /aaa/bb/cc.html、/aa.html 或者 /aa/aa.html。
- 第四个接口估计大家都比较熟悉,在 RESTful 风格的接口设计中估计大家都用过,它接收的请求格式类似于 /hello/aa/bb,其中参数 p1 就对应 aa,参数 p2 对应 bb。
- 第五个接口则用到了正则,name、version 以及 ext 三个参数格式用正则表达出来,它可以接收诸如 /spring-web-3.0.5.jar 格式的请求,最终的参数 name 就是 spring-web,version 就是 3.0.5,ext 则是 .jar。
这是 SpringMVC 中之前就存在的功能,不管你用没用过,反正它一致存在。
那么是谁支撑了这个功能呢?那就是 AntPathMatcher。
AntPathMatcher 是一个实现了 Ant 风格的路径匹配器,Ant 风格的路径规则实际上就是我们前面给大家介绍的那三种路径匹配符,很 Easy。这种路径匹配规则源自 Apache Ant 项目(https://ant.apache.org),Apache Ant 我们现在其实已经很少会用到了,它的替代品就是大家所熟知的 Maven,如果你有幸维护一些 2010 年之前的老项目的话,有可能会接触到 Ant。
AntPathMatcher 实际上在 SpringMVC 中有非常广泛的应用,不仅仅是在 @RequestMapping 中定义接口用到,在其他一些涉及到地址匹配的地方也会用到,例如我们在 SpringMVC 的配置文件中配置静态资源过滤时,也是 Ant 风格路径匹配:
另外像拦截器里的拦截路径注册、跨域处理时的路径匹配等等,都会用到 Ant 风格的路径匹配符。
整体上来说,AntPathMatcher 是 Spring 中一种比较原始的路径匹配解决方案,虽然比较简单,但是它的效率很低,并且在处理 URL 编码的时候也很不方便。
因此,才有了 Spring5 中的 PathPattern。
PathPattern
PathPattern 专为 Web 应用设计,它与之前的 AntPathMatcher 功能大部分比较类似,当然也有一些细微差异,这个松哥后面会说。
如果是 Servlet 应用,目前官方推荐的 URL 匹配解决方案就是 PathPattern(当然你也可以选择较早的 AntPathMatcher),虽然官方推荐的是 PathPattern,但实际上默认使用的依然是 AntPathMatcher;如果你用的是 WebFlux,PathPattern 就是唯一解决方案了。
注意,PathPattern 是一个非常新鲜的玩艺,目前 Spring 最新版是 5.3.4,在 Spring5.3 之前,我们在 Servlet 应用中,也只能选择 AntPathMatcher,从 Spring5.3 之后,我们才可以使用 PathPattern 了。
PathPattern 会将 URL 规则预解析为 PathContainer,它对 URL 地址匹配的处理更加快速,PathPattern 与 AntPathMatcher 的差异主要体现在两个方面:
第一,PathPattern 只支持结尾部分使用 **,如果在路径的中间使用 ** 就会报错,上文中第一个和第三个接口,在 PathPattern 模式下会报错,如下:
因为在中间或者开始使用 ** 极易造成混乱,因此 PathPattern 只支持在结尾使用 **。
第二,PathPattern 支持使用诸如 {*path} 的方式进行路径匹配,这种写法也可以匹配到多层路径,并且将匹配到的值赋值给 path 变量,例如如下一个接口:
@GetMapping("/javaboy/{*path}")
public void hello6(@PathVariable String path) {
System.out.println("path = " + path);
}
如果请求路径是
http://localhost:8080/javaboy/aa,那么参数 path 的值就是 /aa;
如果请求路径是
http://localhost:8080/javaboy/aa/bb/cc/dd,那么参数 path 的值就是 /aa/bb/cc/dd;
这个写法也比较新颖,因为之前的 AntPathMatcher 里边没有这个。
如何使用
默认情况下,SpringMVC 中使用的还是 AntPathMatcher,那么如何开启 PathPattern 呢?很简单,在 SpringBoot 项目中只需要添加如下配置即可:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setPatternParser(new PathPatternParser());
}
}
添加了这个配置后,在我们文章一开始贴出来的代码里,就会进入到 if 分支中,进而使用 PathPattern 去解析请求 URL。
小结
好啦,今天就和小伙伴们聊这么多,大家可以体验一把这个东东,不过注意选择 Spring 的版本哦,一定选择 5.3 之上的版本~大家周末愉快哦~
相关推荐
- 得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践
-
一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...
- warm-flow新春版:网关直连和流程图重构
-
本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...
- 扣子空间体验报告
-
在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...
- spider-flow:开源的可视化方式定义爬虫方案
-
spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...
- solon-flow 你好世界!
-
solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...
- 新一代开源爬虫平台:SpiderFlow
-
SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...
- 通过 SQL 训练机器学习模型的引擎
-
关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...
- 鼠须管输入法rime for Mac
-
鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...
- Go语言 1.20 版本正式发布:新版详细介绍
-
Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...
- iOS 10平台SpriteKit新特性之Tile Maps(上)
-
简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...
- 程序员简历例句—范例Java、Python、C++模板
-
个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...
- Telerik UI for iOS Q3 2015正式发布
-
近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...
- ios使用ijkplayer+nginx进行视频直播
-
上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...
- IOS技术分享|iOS快速生成开发文档(一)
-
前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...
- macOS下配置VS Code C++开发环境
-
本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- httperror403.14-forbidden (63)
- logstashinput (65)
- hadoop端口 (65)
- dockernetworkconnect (63)
- esxi7 (63)
- vue阻止冒泡 (67)
- c#for循环 (63)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- java大写转小写 (63)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)