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

Spring Boot 校验分组(Validation Groups)高级用法全指南

Spring Boot 校验分组(Validation Groups)高级用法全指南

版本:Spring Boot 3.x + Jakarta Bean Validation 3.x
目标:用 同一份 DTO 支撑 “新增 / 修改 / 导入 / 审核” 等多套校验规则,零冗余、零硬编码、易扩展


一、为什么需要校验分组?

场景规则差异示例
新增id 必须为 null
修改id 必须非 null
导入批量字段可空,但格式必须合法
审核只校验备注长度,其余忽略

传统写法:为每个场景写独立 DTO → 类爆炸、重复字段、维护困难
分组写法一个 DTO + N 个场景接口按需启用,极致简洁。


二、核心三要素(牢记即可)

要素作用示例
分组接口(Marker Interface)标记场景interface Create {}
分组注解指定规则生效范围@NotNull(groups = Update.class)
分组校验调用时声明场景@Validated(Create.class)

三、快速上手(3 步走)

1️⃣ 定义分组接口

public interface Create {}   // 新增
public interface Update {}   // 修改
public interface Import {}   // 批量导入
public interface Audit {}    // 审核

2️⃣ 在 DTO 上按场景声明规则

@Data
public class UserDTO {// 新增时 id 必须为 null;修改时 id 必须非 null@Null(groups = Create.class)@NotNull(groups = Update.class)private Long id;// 所有场景必填@NotBlank(groups = {Create.class, Update.class, Import.class})private String username;// 仅导入场景校验邮箱格式@Email(groups = Import.class)private String email;// 仅审核场景校验备注长度@Size(max = 500, groups = Audit.class)private String remark;
}

3️⃣ 在 Controller 指定场景

@RestController
@RequestMapping("/user")
@Validated   // 告诉 Spring 启用方法级校验
public class UserController {@PostMappingpublic String create(@Validated(Create.class) @RequestBody UserDTO dto) {return "新增成功";}@PutMapping("/{id}")public String update(@PathVariable Long id,@Validated(Update.class) @RequestBody UserDTO dto) {dto.setId(id);return "修改成功";}@PostMapping("/batch")public String batch(@Validated(Import.class) @RequestBody List<@Valid UserDTO> list) {return "导入成功";}@PostMapping("/{id}/audit")public String audit(@PathVariable Long id,@Validated(Audit.class) @RequestBody UserDTO dto) {dto.setId(id);return "审核成功";}
}

四、高级技巧(生产常用)

1️⃣ 组继承(减少重复注解)

public interface Create extends Default {}  // 继承默认组
public interface Update extends Default {}

默认组 javax.validation.groups.Default 可省略 groups = Default.class

2️⃣ 分组序列(按顺序校验)

@GroupSequence({Create.class, SecondStep.class})
public interface CreateTwoStep {}
  • 先校验 Create 规则 → 通过后继续 SecondStep避免一次性抛出所有错误

3️⃣ 动态分组(运行时决定)

@Component
public class ValidationGroupSelector {public Class<?> resolveGroup(String operation) {return switch (operation) {case "create" -> Create.class;case "update" -> Update.class;case "import" -> Import.class;default -> Default.class;};}
}

在 Service 层使用:

Set<ConstraintViolation<UserDTO>> violations =validator.validate(dto, groupSelector.resolveGroup(operation));

五、与常见框架集成

框架用法
Spring MVC@Validated(Group) + 全局异常处理
Spring BatchItemProcessor 中手动 validator.validate(item, Import.class)
MapStruct映射后调用 validator.validate(dto, Update.class) 确保 DTO 合法

六、避坑清单

解决
默认组未生效显式继承 Default 或显式声明 groups = Default.class
集合参数未生效使用 List<@Valid DTO> + @Validated(Group)
构造器注入构造器参数上同样加 @Validated(Group)

七、一句话总结

“一个 DTO + N 个 Marker 接口”
让 Spring Boot 的 同一份数据模型不同业务场景 下拥有 不同校验规则
彻底告别 DTO 冗余if-else 校验地狱

http://www.dtcms.com/a/347075.html

相关文章:

  • 从词源和输出生成等角度详细解析PHP中常用文件操作类函数
  • Mac简单测试硬盘读写速度
  • 计算机网络 TLS握手中三个随机数详解
  • 鸿蒙应用网络开发实战:HTTP、WebSocket、文件下载与网络检测全攻略
  • Ubuntu 操作系统深度解析:从入门到精通(2025 最新版)
  • AP5414 LED驱动芯片:高效灵活,专业级照明解决方案
  • 20250823解决荣品RD-RK3588-MID核心板的底板的adb不通
  • Unity其他--【MMD】如何在Unity中制作MMD
  • Go数据结构与算法-常见的排序算法
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘arviz’问题
  • Boost.Asio 库中的 async_read_some用法
  • JAVA核心基础篇-操作符
  • 嵌入式LINUX——————网络TCP
  • 如何在Ubuntu中删除或修改已有的IP地址设置?
  • 在Excel和WPS表格中快速插入多行或多列
  • 生成一个竖直放置的div,宽度是350px,上面是标题固定高度50px,下面是自适应高度的div,且有滚动条
  • LeetCode算法日记 - Day 19:判定字符是否唯一、丢失的数字
  • 可转换债券高频交易Level-2五档Tick级分钟历史数据分析
  • 什么?OpenCV调用cv2.putText()乱码?寻找支持中文的方法之旅
  • Vue3+ElementPlus倒计时示例
  • 入校申请|基于SprinBoot+vue的入校申报审批系统(源码+数据库+文档)
  • [激光原理与应用-332]:结构设计 - Solidworks - 特征(Feature)是构成三维模型的基本单元,是设计意图的载体,也是参数化设计的核心。
  • LeetCode 面试经典 150_数组/字符串_找出字符串中第一个匹配项的下标(23_28_C++_简单)(KMP 算法)
  • 「ECG信号处理——(24)基于ECG和EEG信号的多模态融合疲劳分析」2025年8月23日
  • 构建真正自动化知识工作的AI代理
  • 日志搜索系统前端页面(暂无后端功能)
  • 【leetcode】92. 反转链表2
  • k8s总结
  • Sentinel相关记录
  • 语义通信高斯信道仿真代码