乐趣区

关于springboot:一次SpringBoot版本升级引发的血案

前言
最近项目组降级了 SpringBoot 版本,由之前的 2.0.4 降级到最新版本 2.7.5,却引出了一个大 Bug。
到底是怎么回事呢?
1. 案发现场
有一天,项目组的共事反馈给我说,我之前有个接口在新的测试环境报错了,具体异样是:Missing argment level for method parameter of type Integer。
我过后的第一反馈有点懵,心想这个接口是一个老接口,有一年多的工夫都没改过了,怎么会出问题呢?
他说近期另外一个共事为了部署阿里云服务器,把新测试环境 SpringBoot 的版本升级到了最新版。
之后,在测试的过程中,发现我有个 Get 申请接口报异样了。
该接口代码相似于这样:

在 getCategory 接口中,有两个参数:

type 示意大类,是必传的。
level 示意要返回几级分类,比方:4 级分类,就传 4,是非必传的,默认就是查 4 级分类。

就是这样一个接口的 level 参数,前端没有传参,例如:

后果被 Spring MVC 拦挡间接报错了。
2 报错的起因
从打印的异样信息看,当初 level 参数必须要传值了,之前是可传,可不传的。
我起初本打算自定义 Spring 的转换器,批改一下校验规定,跟老版本保持一致。
这样那些根本接口就不必改了。
但起初发现,被 spring-web-5.3.23 的源码有情的打脸了。
在 org.springframework.web.method.annotation 包下的 AbstractNamedValueMethodArgumentResolver 类的 resolveArgument 办法中:多了这样的校验。如果该参数为空,没有设置默认值,required 属性为 true,并且不是 Optional 类型,则执行 handleMissingValueAfterConversion 办法。该办法会调用 handleMissingValue 办法,具体代码如图中所示:

最初会抛出之前我看到的那个异样。
起因最新版本的 Spring 中不容许 Get 接口的申请参数,在不应用 @RequestParam 注解时,值为空的状况呈现了。
3 如何解决问题?
想要解决下面的报错问题,其实很简略,只需在 level 参数前加 @RequestParam 注解,并且设置 required 属性为 false。
例如:

然而前面发现,我的项目中不只我这一个接口要调整,其余好多共事的接口,也有相似的问题,须要批改的接口很多。
这个改变的工作量不小。
哭晕在测试。。。
后话
这个问题有很多人中招,所以十分有必要把这个问题分享给大家,防微杜渐。
我之前 level 参数不加 @RequestParam 注解,也没设置 required 属性,过后持有的心态是 Spring 有默认值,有些注解不加,程序也能失常运行,既然这样就能够少写点代码,并且在过后的版本测试过,没有呈现过什么问题。
这种状况其实是 Spring 框架的一个 bug,曾经在最新版本中被修复了。。。
连忙 review 一下你们的代码,看看有没有相似的用法,不然迟早有一天也会中招。

退出移动版