滥用@PathVariable导致bug原因分析解决

 更新时间:2022年12月12日 16:09:53   作者:程序员拾山  
这篇文章主要为大家介绍了滥用@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个匹配步骤

3个匹配步骤

1,根据Path精准匹配

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

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

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

最后

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

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

以上就是滥用@PathVariable导致bug原因分析解决的详细内容,更多关于@PathVariable导致bug的资料请关注脚本之家其它相关文章!

相关文章

  • Spring boot中使用ElasticSearch的方法详解

    Spring boot中使用ElasticSearch的方法详解

    这篇文章主要给大家介绍了关于Spring boot中使用ElasticSearch的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • Mybatis-Plus使用p6spy对SQL性能进行监控的方法

    Mybatis-Plus使用p6spy对SQL性能进行监控的方法

    这篇文章主要介绍了Mybatis-Plus使用p6spy对SQL性能进行监控的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Java webSerivce的使用看完你就明白了

    Java webSerivce的使用看完你就明白了

    因为前段时间,需要使用到webService来调用公司的其他系统api接口,但是请求方式和我熟知的http请求不一样,是基于soap协议来传输xml数据格式,请求的参数极其复杂,需要封装多层xml数据格式,并且我不知道对方的api接口是什么语言,甚至不知道他们存在于什么平台
    2022-03-03
  • 关于jvm的垃圾回收器以及触发full gc的场景

    关于jvm的垃圾回收器以及触发full gc的场景

    这篇文章主要介绍了关于jvm的垃圾回收器以及触发full gc的场景,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Java class文件格式之属性_动力节点Java学院整理

    Java class文件格式之属性_动力节点Java学院整理

    在本文中, 主要讲解了class文件中的一些属性。 这些属性可以出现在class文件中的对个地方, 用来描述一些其他信息
    2017-06-06
  • 三分钟教你如何在IDEA中快速创建工程的方法

    三分钟教你如何在IDEA中快速创建工程的方法

    这篇文章主要介绍了三分钟教你如何在IDEA中快速创建工程的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • 详解Java redis中缓存穿透 缓存击穿 雪崩三种现象以及解决方法

    详解Java redis中缓存穿透 缓存击穿 雪崩三种现象以及解决方法

    缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大
    2022-01-01
  • Java向数据库中插入数据后获取自增ID的常用方法

    Java向数据库中插入数据后获取自增ID的常用方法

    有时候因为新增的需求需要获取刚刚新增的数据的自增的主键ID,下面这篇文章主要给大家介绍了关于Java向数据库中插入数据后获取自增ID的常用方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • Java实战项目 健身管理系统

    Java实战项目 健身管理系统

    本文是一个Java语言编写的实战项目,是一个健身管理系统,主要用到了ssm+springboot等技术,技术含量笔记高,感兴趣的童鞋跟着小编往下看吧
    2021-09-09
  • MyBatis Plus之实现动态排序方式

    MyBatis Plus之实现动态排序方式

    这篇文章主要介绍了MyBatis Plus之实现动态排序方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02

最新评论