当前位置: 首页 > article >正文

【Spring】@Size 无法拦截null的原因

问题复现

  • 在构建 Web 服务时,我们一般都会对一个 HTTP 请求的 Body 内容进行校验,例如我们来看这样一个案例及对应代码。
  • 当开发一个学籍管理系统时,我们会提供了一个 API 接口去添加学生的相关信息,其对象定义参考下面的代码:
    import lombok.Data;
    import javax.validation.constraints.Size;
    @Data
    public class Student {
        @Size(min = 1, max = 10)
        private String name;
        private short age;
    }
    
  • 如上代码所示,我们想针对学生的姓名进行一个判断,不能为空,并且长度为1-10。
  • 然后,我们以下面的 JSON Body 做测试:
    {
      "name": "",
      "age": 10,
      "phone": {"number":"12306"}
    }
    
  • 测试结果符合我们的预期,但是假设更进一步,用下面的 JSON Body(去除 name 字段)做测试呢?
    {
      "age": 10,
      "phone": {"number":"12306"}
    }
    
  • 我们会发现校验失败了。这结果难免让我们有一些惊讶,也倍感困惑:@Size(min = 1, max = 10) 都已经要求最小长度为 1 了,难道还只能约束空字符串(即“”),不能约束 null?

案例分析

  • 如果我们稍微留心点的话,就会发现其实 @Size 的 Javadoc 已经明确了这种情况,参考下图:
    在这里插入图片描述
  • 如图所示,“null elements are considered valid” 很好地解释了约束不住 null 的原因。当然纸上得来终觉浅,我们还需要从源码级别解读下 @Size 的校验过程。
  • 这里我们找到了完成 @Size 约束的执行方法,参考 SizeValidatorForCharSequence#isValid 方法:
    public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
        if ( charSequence == null ) {
            return true;
        }
        int length = charSequence.length();
        return length >= min && length <= max;
    }
    
  • 如代码所示,当字符串为 null 时,直接通过了校验,而不会做任何进一步的约束检查。

问题修正

  • 关于这个问题的修正,其实很简单,我们可以使用其他的注解(@NotNull 或 @NotEmpty)来加强约束,修正代码如下:
    @NotEmpty
    @Size(min = 1, max = 10)
    private String name;
    
  • 完成代码修改后,重新测试,你就会发现约束已经完全满足我们的需求了。

http://www.kler.cn/a/500975.html

相关文章:

  • Linux web渗透攻防
  • 图像处理中实现 C++ 和 Python 的高效通信——ZeroMQ protobuf
  • Git | git revert命令详解
  • [云原生之旅] K8s-Portforward的另类用法, 立省两个端口
  • docker-compose方式部署单机版RocketMQ
  • 探索AGI:智能助手与自我赋能的新时代
  • Julia语言的软件工程
  • .NET Core NPOI 导出图片到Excel指定单元格并自适应宽度
  • Cesium加载地形
  • STM32 : 波特率发生器
  • ceph 数据均衡
  • K11082 加密与解密
  • Vue2+OpenLayers使用Overlay实现点击获取当前经纬度信息(提供Gitee源码)
  • 数据结构讲解
  • es分页查询
  • (STM32笔记)十二、DMA的基础知识与用法 第二部分
  • el-table横向滚动条,滚动后消失
  • 解锁动态规划的奥秘:从零到精通的创新思维解析(5)
  • MathBuddyGUI:带控制系统仿真功能、积分运算的计算器,MATLAB课程设计
  • Golang笔记——Interface类型
  • Audio音频输出通道
  • defineProps 和 Pinia 的使用方法和区别总结
  • Mac Mini 最优雅的备份方式:使用极空间实现自动整机备份
  • 基于ILI9341液晶屏+STM32U5单片的显示试验
  • OKR 极简史及理解
  • 无需昂贵GPU:本地部署开源AI项目LocalAI在消费级硬件上运行大模型