news 2026/6/15 21:25:54

Spring Boot 参数校验进阶:抛弃复杂的 Group 分组,用 @AssertTrue 实现“动态逻辑校验”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 参数校验进阶:抛弃复杂的 Group 分组,用 @AssertTrue 实现“动态逻辑校验”

一、 背景:标准注解不够用了怎么办?

在 Spring Boot 开发中,我们习惯了使用@NotNull,@Size,@Pattern来校验参数。但是,业务往往比这复杂得多。

场景举例:
我们有一个用户保存接口(UserSaveReqVO),既用于新增,也用于修改

  1. 新增时id为空,但password必须填。
  2. 修改时id必填,但password可以为空(为空代表不修改密码)。

痛点
如果直接在password字段上加@NotBlank,那么修改接口也会报错。如果不加,新增接口就不安全。怎么解决?


二、 什么是 @AssertTrue?

@AssertTrue是 Bean Validation (Hibernate Validator) 提供的一个标准注解。

  • 字面含义:断言为真。
  • 作用对象:通常用于Boolean 类型的字段返回 Boolean 类型的方法
  • 校验规则
    • 如果值为true,校验通过
    • 如果值为false,校验失败,抛出异常并返回message中的错误信息。

核心价值:它允许我们在 DTO 内部编写一段 Java 代码,来进行自定义的、跨字段的、带有业务逻辑的校验。


三、 实战示例:一行代码搞定“新增必填,修改选填”

我们不需要定义两个 DTO,也不需要搞复杂的 Group,直接在 VO 内部写一个方法即可。

importcom.fasterxml.jackson.annotation.JsonIgnore;importio.swagger.v3.oas.annotations.media.Schema;importlombok.Data;importjavax.validation.constraints.AssertTrue;importjava.util.Objects;@Data@Schema(description="用户保存请求 VO")publicclassUserSaveReqVO{@Schema(description="用户ID (新增为空,修改必填)")privateLongid;@Schema(description="账号")privateStringusername;@Schema(description="密码")privateStringpassword;// =================================================// 核心黑科技:自定义逻辑校验// =================================================@AssertTrue(message="新增用户时,密码不能为空")@JsonIgnore// ⚠️ 坑点预警:必须加这个,否则会多出一个名为 passwordValid 的字段返回给前端publicbooleanisPasswordValid(){// 逻辑拆解:// 1. 如果 id 不为空,说明是“修改模式”。// 修改模式下对密码没要求,直接返回 true (通过)。if(id!=null){returntrue;}// 2. 如果 id 为空,说明是“新增模式”。// 新增模式下,密码必须有值。returnpassword!=null&&!password.trim().isEmpty();}}

Controller 使用方式:
完全不用改,照常加@Valid即可。

@PostMapping("/save")publicCommonResult<Boolean>saveUser(@Valid@RequestBodyUserSaveReqVOreqVO){// 如果校验失败,这里进不来,全局异常处理器会处理returnsuccess(userService.saveUser(reqVO));}

四、 为什么它比 Validation Groups (分组校验) 更好?

很多教程会推荐使用groups属性来解决这个问题,但在实战工程中,@AssertTrue 往往更胜一筹

1. 避免“注解地狱”与“类爆炸”
  • Groups 方案:你需要定义CreateGroupUpdateGroup接口。然后字段上写@Null(groups=Create.class),@NotNull(groups=Update.class)… 代码看起来很乱。
  • AssertTrue 方案:逻辑内聚在一个 Java 方法里,if-else清晰易读。
2. 代码高内聚 (High Cohesion)
  • Groups 方案:校验逻辑是割裂的。DTO 定义规则,Controller 决定触发哪个 Group。如果你在 Controller 里忘了写@Validated(CreateGroup.class),校验就失效了,容易出 Bug。
  • AssertTrue 方案:校验逻辑完全封装在 DTO 内部。Controller 不需要关心是新增还是修改,只要加个@Valid,DTO 自己会根据 ID 是否为空来判断该检查什么。
3. 解决“跨字段依赖”问题

这是 Group 做不到的。

  • 需求:如果type是 “手机注册”,则mobile必填;如果type是 “邮箱注册”,则email必填。
  • AssertTrue:直接写个if (type==1) return mobile != null;,轻松搞定。

五、 避坑指南

在使用@AssertTrue这种方法级校验时,有两个细节必须注意:

  1. 方法名必须以isget开头
    校验器是按照 JavaBean 规范来找方法的。建议使用isValid()isXxxValid()
  2. 必须加上@JsonIgnore
    这是最容易踩的坑。如果不加,Jackson 序列化时会把这个方法当成一个属性(比如passwordValid: true)返回给前端,或者导致 Swagger 文档里多出莫名其妙的字段。

六、 总结

  • 简单校验(非空、长度、正则):直接用@NotNull,@Size等标准注解。
  • 场景区分(新增/修改)或跨字段逻辑(A有值则B必填):优先推荐使用@AssertTrue+ 自定义方法

它让你的代码更内聚、更易读,并且避免了 Controller 层繁琐的分组配置。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 11:22:14

为Shopify店铺带来源源不断的流量:一份从零开始的SEO实操指南

Shopify 会自动处理技术性 SEO 基础工作&#xff0c;但出现在搜索引擎中仍然需要手动优化。 本指南将带您一步步优化您的Shopify商店以适应搜索引擎。 你将学习Shopify自动管理哪些SEO任务&#xff0c;哪些需要你关注&#xff0c;以及如何优先处理快速赢得带来流量的任务。 到最…

作者头像 李华
网站建设 2026/6/15 12:18:43

【MongoDB实战】6.3 索引优化实战:慢查询解决(补充)

文章目录 6.3 索引优化实战:慢查询解决 6.3.1 识别慢查询:explain()方法深度解析 核心概念 实操步骤1:准备测试数据集 实操步骤2:执行慢查询并分析执行计划 执行结果解读(未加索引) 6.3.2 优化案例:慢查询索引优化实战 核心优化思路 实操步骤1:创建复合索引 索引列表输…

作者头像 李华
网站建设 2026/6/15 13:26:12

Cordova与OpenHarmony换盆记录管理

欢迎大家加入开源鸿蒙跨平台开发者社区&#xff0c;一起共建开源鸿蒙跨平台生态。 换盆管理系统概述 换盆是植物生长过程中的重要环节&#xff0c;它为植物提供更多的生长空间和新鲜的土壤。在Cordova框架与OpenHarmony系统的结合下&#xff0c;我们需要实现一个完整的换盆记录…

作者头像 李华
网站建设 2026/6/15 11:48:18

SVG 多边形

SVG 多边形 SVG(可缩放矢量图形)是一种基于可缩放矢量图形的图形和图像的文件格式,它可以用于网页设计、动画制作以及图表展示等领域。在SVG中,多边形是一个非常基础且强大的图形元素。本文将详细介绍SVG多边形的定义、属性、创建方法以及在实际应用中的使用技巧。 一、S…

作者头像 李华
网站建设 2026/6/15 11:49:55

10_C 语言进阶之避坑指南:浮点数与精度损失—— 不可思议的 “量化误差”

C 语言进阶之避坑指南:浮点数与精度损失—— 不可思议的 “量化误差” 浮点数是 C 语言中处理小数、科学计数法数值的核心类型,看似简单的float和double,却暗藏大量容易被忽视的陷阱 —— 从精度丢失导致的计算错误,到浮点数比较的逻辑漏洞,再到嵌入式环境下的浮点运算支…

作者头像 李华
网站建设 2026/6/15 15:36:30

通信系统仿真:通信系统基础理论_(2).信号与系统

信号与系统 信号的分类 在通信系统中,信号是信息传递的基本载体。根据不同的特性,信号可以分为多种类型。了解信号的分类是进行通信系统仿真和分析的基础。 连续时间信号与离散时间信号 连续时间信号是指在时间上连续变化的信号,可以用数学函数 x(t)x(t)x(t) 表示,其中…

作者头像 李华