源码剖析@ApiImplicitParam对@RequestParam的required属性的侵入性

使用SpringCloud构建项目时,使用Swagger生成相应的接口文档是推荐的选项,Swagger能够提供页面访问,直接在网页上调试后端系统的接口, 非常方便。最近却遇到了一个有点困惑的问题,演示接口示例如下(原有功能接口带有业务实现逻辑,这里简化了接口):

/** * @description: 演示类 * @author: Huang Ying **/ @Api(tags = "演示类") @RestController @Slf4j public class DemoController { @ApiOperation(value = "测试接口") @ApiImplicitParams({ @ApiImplicitParam(name = "uid", value = "用户ID", paramType = "query", dataType = "Long") }) @RequestMapping(value = "/api/json/demo", method = RequestMethod.GET) public String auth(@RequestParam(value = "uid") Long uid) { System.out.println(uid); return "the uid: " + uid; } }

问题出在接口参数uid的必填性上,@RequestParam注解里require默认为true,要求必填,但@ApiImplicitParam注解里require默认为false,要求非必填,该业务接口在进行功能联调时,uid居然能得到一个null值,按照一般认知习惯@ApiImplicitParam注解的主要作用是生成接口文档,不应该对@RequestParam的属性有侵入性才对,目前反馈的bug,让我怀疑@ApiImplicitParam是不是会侵入@RequestParam的require属性?

框架选型、版本及主要功能 项目搭建

SpringBoot版本:2.1.6.RELEASE
SpringCloud版本:Greenwich.SR3

业务模块

SpringCloud业务模块使用的swagger:

swagger bootstrap ui 1.9.6 增强swagger ui样式
spring4all-swagger 1.9.0.RELEASE 配置化swagger参数,免去代码开发

业务网关

SpringCloud业务网关使用的swagger:

knife4j 2.0.1 增强swagger ui样式(网关用gateway搭建,swagger使用knife4j-spring-boot-starter依赖,可以聚合业务模块的swagger文档)

此次的范围只针对SpringCloud业务模块,暂时不涉及业务网关的Swagger文档。

测试工具

测试工具目前有两个:
swagger doc:使用浏览器进行访问,如下图:

postman:手动配置接口参数,示例:

案例实战 接口测试1

接口示例如开篇所示,我们先使用如下接口,全部使用默认值,即@ApiImplicitParam的required为false,@RequestParam的required为true:

@ApiOperation(value = "测试接口") @ApiImplicitParams({ @ApiImplicitParam(name = "uid", value = "用户ID", paramType = "query", dataType = "Long") }) @RequestMapping(value = "/api/json/demo", method = RequestMethod.GET) public String auth(@RequestParam(value = "uid") Long uid) { System.out.println(uid); return "the uid: " + uid; }

看swagger的结果:

看postman的结果:

接口测试2

我们修改@ApiImplicitParam的required值为true,@RequestParam不变,重启模块
@ApiImplicitParam(name = "uid", value = "用户ID", paramType = "query", required = true, dataType = "Long")

看swagger的结果:

通过调试浏览器可以发现,为空校验是js完成的,js判断为空后,并未发起请求到后端,这样我们可以认为swagger内@ApiImplicitParam的required参数生效了。

接口测试3

在前面我们使用postman测试接口时,发现参数项是空的,我们加上参数,但不写值测试后,结果让人诧异:

并且无论@ApiImplicitParam的required值如何修改,结果都是一样的,肯定有一个地方是搞错了,导致我们误判。

后来仔细查阅资料,发现是我们对@RequestParam的required参数理解错了,这个required为true的含义是:接口参数名一定要存在,但参数后面有没有值它管不着。拿刚刚的例子来说:

这两个请求是通过的: localhost:8080/api/json//demo?uid localhost:8080/api/json//demo?uid= 只有这种请求是不通过的: localhost:8080/api/json//demo? 小结论

经过上述三个接口的测试场景,我们至少可以明确3点:

@ApiImplicitParam的required参数不会对@RequestParam的required值造成侵入,它们俩不相关。

@ApiImplicitParam的required参数会影响swagger doc的js逻辑判断,为空校验是在js层面上完成的。

@RequestParam的required参数默认情况下只会校验是否有该参数名,不校验它是否有值。

源码剖析 swagger部分

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfyzp.html