因为滥用@PathVariable导致的Bug,开发同学又背锅了

开发 前端
@PathVariable可以让我们开发接口的时候省去一些功夫,但是需要注意到,如果绑定的参数带有特殊字符,就有可能导致非预期的Bug。

前言

最近测试同学反馈,上周上线的一个功能会偶然性的报404,按理说这个功能在测试环境已经测试通过,也在线上运行了好几天,怎么会突然报错呢。

一开始以为是前端同学请求的接口有误,但是测试又说只是偶然性的404,几率也不高,于是打开日志找到对应的接口,一眼看到了接口上定义的@PathVariable,再一看参数,基本就确定是开发同学为了偷懒又误用@PathVariable导致的了。

先说结论吧:@PathVariable可以使请求参数动态的绑定到URL上,但是如果请求参数中包含特殊字符,比如 /,就可能导致Spring匹配到一个错误的URL,或者匹配不到合适的URL。

复现

下面,我用一个简单的伪代码复现一下这个bug,与大家分析一下这个bug发生的原因,以及如何解决,最后顺便再通过源码加深一下印象。

如下,我们定义一个接口,并且通过@PathVariable将入参动态的绑定到URL上。

@RestController
@RequestMapping(value = "/demo")
public class DemoController {
@GetMapping(value = "/getVal/{val}")
public ResponseEntity<Object> getVal(@PathVariable String val){
System.out.println("参数:" + val);
return ResponseEntity.ok(val);
}
}

然后我们测试一下这个接口:

正常情况下,我们输入一个普通无特殊符号的参数,控制台也成功打印了出来。

但是业务参数往往是不可控的,比如当参数变成“ hello/world”时,代码就不能正常执行了。

大家可以从图中看到,Spring将原本预期的URL:/demo/getVal/{val},解析成了/demo/getVal/hello/world。

而之所以测试同学最近才发现这个接口有问题,也正是因为上线之初并没有遇到带有/的参数,所以接口看起来是正常的,直到最近在生产环境遇到了一个带/的参数。

正确的做法是:将URL定义为/demo/getVal,然后将参数通过表单或者query的方式传递。

​解决的办法很简单,相信有点经验的同学都能很快将这个问题修复。

但是知其然,更要知其所以然,顺着这个问题,我们探究一下Spring究竟是如何解析URL的。​

首先,我们找到Spring webmvc的包,在
org.springframework.web.servlet.handler包下找到AbstractHandlerMethodMapping类,这个类就是会将我们定义的mapping和URL绑定起来。

这个类中的lookupHandlerMethod方法,会查找当前请求的最佳匹配处理程序方法,并且如果找到多个匹配项,就选择最佳匹配项。

分析这个方法,我们可以得到这样3个匹配步骤:

1、根据Path精准匹配

2、如果精准匹配没有成功,就开始模糊匹配

3、如果模糊匹配还匹配不上,就返回null

至此,一个URL解析的过程就完毕了。单看源码可以发现,逻辑其实并不复杂,就是一个按照规则不断匹配的过程。

最后

总得来说,@PathVariable可以让我们开发接口的时候省去一些功夫,但是需要注意到,如果绑定的参数带有特殊字符,就有可能导致非预期的bug。

一般来说,@PathVariable比较适合绑定整型的参数,如果是字符串类的参数,建议大家还是通过表单或json的方式传参。

责任编辑:姜华 来源: 今日头条
相关推荐

2019-12-17 10:01:40

开发技能代码

2017-09-25 10:52:27

2021-08-16 15:50:24

辅助驾驶自动驾驶蔚来

2019-12-03 13:57:38

CIO背锅IT

2019-02-14 13:30:54

内存泄露运维

2021-02-02 09:13:11

索引SQL数据库

2018-12-26 17:36:37

开发者技能阿里

2020-10-21 11:20:42

MySQL数据库Bug

2019-09-17 10:31:51

岗位产品程序员

2019-01-04 10:13:22

苹果中国市场iPhone

2019-01-16 18:11:28

程序员技能开发者

2018-10-19 16:35:20

运维

2022-11-26 10:36:30

MySQLSkyWalking应用性能

2020-12-02 06:13:29

Redis连接池

2022-11-29 10:27:46

SkyWalkingMySQL延迟时间

2021-12-14 05:54:23

Windows 11操作系统微软

2021-09-12 17:27:41

PeerDepende项目命令

2020-12-09 11:00:44

Nginx 运维Tomcat

2017-09-12 16:18:22

ICO区块链互联网+

2022-04-06 10:36:24

技术管理
点赞
收藏

51CTO技术栈公众号