[排坑]Spring Boot @RequestParam的required=true但参数依然为null

本文探讨了在Spring Boot中使用@RequestParam注解时,即使设置required=true,参数仍可能为null的情况。问题源于枚举类型的序列化处理,自定义的序列化在反序列化时返回了null,导致参数验证未生效。总结建议在反序列化时避免返回null,而是抛出异常以确保required=true的有效性。

使用场景:

使用Spring Boot的@RequestParam注解时,我知道required的默认值是true,理论上来讲,被注解标注的参数如果为null,Spring Boot应该抛出异常。但实际上没有。

问题描述:

	
    public RestObjectResponse<xx> xxx(@RequestParam(value = "role")UserRole role) {
        return xxx;
    }

从上面的代码来看,如果role为null,应该会直接抛出异常,因此在内部的代码中我就没有校验role是否为null,但事实上null被传进来了。

原因分析:

作为常用的类型,比如Integer、String等,为null会抛出异常。我们这个是枚举类型,遇到这样的问题,我们先思考下面的三个问题

  • required=true是判断传入的url参数或body参数为空吗?
  • required=true是判断最终方法传入被RequestParam修饰的参数对象为空吗?
  • 是不是对枚举的序列化处理出现了什么问题

先分析枚举序列化

因为我自定义了枚举的序列化,但是在反序列化过程中直接返回的null值。这也应该是造成参数为null的根源。那么通过这个现象我们可以思考,required=true判断的可能仅仅是参数是否为null,当参数不为空,但在反序列化过程中产生的null,是不被检查的。

总结

为了保证required=true 的可信度,在反序列化时,不应该返回null,如果出现不能反序列化的情况,应该抛出异常。

如下代码分页未生效,请优化代码 @ApiOperation(value = "订单多条件查询接口", notes = "订单多条件查询接口") @GetMapping("order_query") public Result<?> orderQuery( @RequestParam @ApiParam(value = "当前页") Integer current, @RequestParam @ApiParam(value = "页大小") Integer size, @RequestParam(required = false) @ApiParam(value = "会员编号") String memberId, @RequestParam(required = false) @ApiParam(value = "会员等级【A,B,C】") String memberLevel, @RequestParam(required = false) @ApiParam(value = "分账是否已完结: 0-未完结, 1-已完结") Boolean profitSharingFinished, @RequestParam(required = false) @ApiParam(value = "分账状态: PENDING-待分账, PROCESSING-分账中, SUCCESS-分账成功, PARTIAL_SUCCESS-部分成功, FAILED-分账失败, CLOSED-已关闭") String profitSharingStatus, @RequestParam(required = false) @ApiParam(value = "微信支付订单号。用户支付成功后,由回调通知传来。未支付时为空。") String transactionId, @RequestParam(required = false) @ApiParam(value = "订单状态: NOTPAY:未支付, SUCCESS:支付成功, CLOSED:已关闭, REFUND:已退款") String status, @RequestParam(required = false) @ApiParam(value = "订单支付成功时间-开始") Date startTime, @RequestParam(required = false) @ApiParam(value = "订单支付成功时间-结束") Date endTime ) { Page<Orders> page = new Page<>(current, size); Page<Orders> ordersPage = ordersService.lambdaQuery() .like(ObjectUtil.isNotEmpty(memberId), Orders::getMemberId, memberId) .like(ObjectUtil.isNotEmpty(memberLevel), Orders::getMemberLevel, memberLevel) .eq(ObjectUtil.isNotEmpty(profitSharingFinished), Orders::getProfitSharingFinished, profitSharingFinished) .eq(ObjectUtil.isNotEmpty(profitSharingStatus), Orders::getProfitSharingStatus, profitSharingStatus) .eq(ObjectUtil.isNotEmpty(transactionId), Orders::getTransactionId, transactionId) .eq(ObjectUtil.isNotEmpty(status), Orders::getStatus, status) .between((ObjectUtil.isNotEmpty(startTime) && ObjectUtil.isEmpty(endTime)), Orders::getPaidAt, startTime, endTime) .orderByDesc(Orders::getCreatedAt) .page(page); return Result.ok(ordersPage); }
最新发布
09-13
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值