13 Validation校验在springboot中使用
1 引入依赖Spring Boot 3.x 也使用这个 starter但包名迁移到了 jakarta.validation。dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId/dependency2 在 DTO 上加注解publicclassUserDTO{NotBlank(message用户名不能为空)privateStringusername;Email(message邮箱格式不正确)privateStringemail;NotNull(message年龄不能为空)Min(value0,message年龄不能小于0)privateIntegerage;}3 Valid触发默认校验PostMapping(/users)publicResultaddUser(ValidRequestBodyUserDTOuser){returnResult.success(添加成功);}4 Validated触发分组校验4.1 定义分组接口publicinterfaceAddGroup{}publicinterfaceUpdateGroup{}4.2 在 DTO 上用 groups 指定分组注意没写 groups 的注解属于 默认分组 Default.class。如果写了 groups它只属于指定分组默认分组不会触发。publicclassUserDTO{// 新增和修改都需要 idNotNull(messageid不能为空,groups{UpdateGroup.class})privateLongid;NotBlank(message用户名不能为空,groups{AddGroup.class,UpdateGroup.class})privateStringusername;Email(message邮箱格式不正确,groups{AddGroup.class})privateStringemail;NotNull(message年龄不能为空,groups{AddGroup.class,UpdateGroup.class})Min(value0,message年龄不能小于0,groups{AddGroup.class,UpdateGroup.class})privateIntegerage;}4.3 方法参数上用 groups 指定分组PostMapping(/add)publicRadd(Validated(AddGroup.class)RequestBodyOrderDTOorder){...}5 Valid和Validated区别参考文章别再混淆了一文带你搞懂Valid和Validated的区别维度ValidValidated来源JSR 303/380 标准javax.validation/jakarta.validationSpring 扩展org.springframework.validation.annotation分组校验❌ 不支持✅ 支持Validated(AddGroup.class)嵌套校验✅ 支持可标在字段上触发子对象校验❌ 不支持不能标在字段上可用位置方法参数、成员变量递归校验、构造函数参数方法参数、方法、类 开启该类校验校验失败异常MethodArgumentNotValidExceptionMethodArgumentNotValidExceptionController 参数ConstraintViolationExceptionService 层 AOP5.1 类上的 Validated开启方法级校验下面情况 类上不用添加Validated开启方法校验默认触发校验。场景情况RequestBody对象参数Valid RequestBody会触发 DTO 内部校验ModelAttribute/ 表单绑定对象表单提交、查询参数绑定到对象时Valid也能触发校验RequestParam、PathVariable、Service 方法参数这些不是RequestBodyValid放在参数上通常不会自动生效需要类上加Validated走方法级校验下面情况 类上必须加Validated开启方法校验否则NotBlank校验不生效RestControllerRequestMapping(/brand)Validated// 关键类上必须加 ValidatedpublicclassBrandController{/** * 按品牌名称查询 */GetMapping(/search)publicRsearch(RequestParam(name)NotBlank(message品牌名称不能为空)Stringname){returnR.ok();}}5.2 方法参数上的Valid/Validated分组与嵌套Validated可以实现分组校验Valid无此功能。 Valid可以实现嵌套校验Validated不能触发。public R save(Valid RequestBody BrandEntity brand)public R save(Validated(AddGroup.class) RequestBody BrandEntity brand)嵌套校验举例publicclassBrandEntity{privateStringname;// 嵌套对象privateAddressEntityaddress;}如果你用 ValidSpring 不仅会校验 BrandEntity 的 name还会自动进入 AddressEntity 里面去校验它的字段。如果你用Validated不会进入 AddressEntity 里面。如果想要同时实现分组校验和嵌套校验Validated修饰方法参数并在AddressEntity嵌套对象上添加Valid。5.3 成员变量上的Valid嵌套Valid private Address address;这是它和 Validated 的关键区别之一开启嵌套校验publicclassUserDTO{NotBlank(message姓名不能为空)privateStringname;NotNull(message地址不能为空)Valid// 加上 Valid会递归校验嵌套对象privateAddressDTOaddress;}所以Validated修饰的方法参数内部可以在成员private AddressDTO address上添加Valid实现分组校验和嵌套校验。6 异常处理6.1全局异常处理参考文章SpringBoot 使用Spring Validation实现接口参数校验全局异常处理类只需要在类上标注RestControllerAdvice并在处理相应异常的方法上使用ExceptionHandler注解写明处理哪个异常即可。RestControllerAdvice本质上是Component可以注入全局异常处理bean。配置basePackages参数处理指定包下抛出的异常。如果不指定则会处理所有的Controller标注的类抛出的异常。ExceptionHandler 标注异常处理方法其value标注要处理的异常类型一般配置一个value Exception.class处理其他未配置异常类型RestControllerAdvice(basePackagescom.atguigu.gulimall.product.controller)publicclassGulimallExceptionControllerAdvice{ExceptionHandler(valueMethodArgumentNotValidException.class)publicRhandleValidException(MethodArgumentNotValidExceptione){BindingResultbindingResulte.getBindingResult();HashMapString,StringerroMapnewHashMap();bindingResult.getFieldErrors().forEach((fieldError-{erroMap.put(fieldError.getField(),fieldError.getDefaultMessage());}));returnR.error(BizCodeEnume.VALID_EXCEPTION.getCode(),BizCodeEnume.VALID_EXCEPTION.getMsg()).put(data,erroMap);}ExceptionHandler(valueException.class)publicRhandleException(Exceptionexception){returnR.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());}}6.2 BingResultBindingResult 是 Spring MVC 里用来接收参数校验结果的对象。校验失败时它会把错误信息存起来而不会直接抛异常。它必须紧跟在被 Valid 或 Validated 标注的参数后面PostMapping(/user)publicStringcreateUser(ValidRequestBodyUseruser,BindingResultresult){if(result.hasErrors()){Stringmsgresult.getFieldErrors().stream().map(e-e.getField(): e.getDefaultMessage()).collect(Collectors.joining(; ));returnResult.fail(400,msg);}...}方法作用hasErrors()是否有校验错误hasFieldErrors()是否有字段级别的错误getFieldErrors()获取所有字段错误列表getFieldError(name)获取指定字段的第一个错误getAllErrors()获取所有错误含全局错误getErrorCount()错误总数7 自定义校验注解7.1 自定义注解PhoneDocumentedConstraint(validatedBy{PhoneValidator.class})Target({ElementType.FIELD,ElementType.PARAMETER})Retention(RetentionPolicy.RUNTIME)publicinterfacePhone{Stringmessage()default手机号格式校验不正确;Class?[]groups()default{};Class?extendsPayload[]payload()default{};StringphoneReg()default^1[3-9]\\d{9}$;}Constraint(validatedBy PhoneValidator.class):指定7.2 注解校验处理方法PhoneValidator这里三个属性是 Bean Validation 规范要求保留的属性作用message()校验失败时的提示信息groups()分组校验使用payload()附加元数据一般默认即可7.2 注解校验处理方法publicclassPhoneValidatorimplementsConstraintValidatorPhone,String{privateStringregPhone;Overridepublicvoidinitialize(PhoneconstraintAnnotation){//获取注解中phoneReg的值StringphoneRegconstraintAnnotation.phoneReg();this.regPhonephoneReg;}OverridepublicbooleanisValid(Stringvalue,ConstraintValidatorContextcontext){//value匹配正则表达式返回是否符合//为空时交由其他校验如NotBlank处理此处直接视为通过if(valuenull||value.isEmpty()){returntrue;}returnvalue.matches(this.regPhone);}}ConstraintValidatorA, T的两个泛型含义是A自定义注解类型。T被校验字段的数据类型。isValid(String value, ConstraintValidatorContext context)两个参数含义value当前正在被校验的那个值。context校验上下文对象用来控制“校验失败后怎么报错”。修改错误提示的message消息。isValid方法返回布尔类型代表校验通过与否。7.3 使用· DTO层DatapublicclassPhoneDTO{NotNull(message姓名不能为空)privateStringname;Phone(phoneReg^15[3-9]\\d{8}$,message请填写15开头的手机号码)privateStringphone;}· Controller层RestControllerRequestMapping(product/category)publicclassCategoryController{RequestMapping(/test/phone)publicRtestPhone(ValidRequestBodyPhoneDTOphone,BindingResultbindingResult){StringerrorMessagenull;if(bindingResult.hasErrors()){errorMessagebindingResult.getFieldErrors().get(0).getDefaultMessage();returnR.error(400,参数错误).put(errors,errorMessage);}returnR.ok().put(page,errorMessage);}}7.4 Http测试POST http://localhost:10001/product/category/test/phone Content-Type: application/json { name: test, phone: 1381234567 }8 常见的Validation注解8.1 空值校验注解适用类型校验规则用例NotNull任意类型不能为null但可以是空字符串、空集合NotNull(messageid不能为空) private Long id;NotBlankString不能为null且去除首尾空格后长度必须大于 0NotBlank(message用户名不能为空) private String username;NotEmptyString、集合、数组、Map不能为null且长度/元素个数大于 0NotEmpty(message标签不能为空) private ListString tags;简单区分字符串必填优先用 NotBlank集合/数组必填用 NotEmpty非字符串对象、数字、日期用 NotNull。8.2 字符串格式与长度注解适用类型校验规则用例Min数值类型必须 ≥ 指定值Min(18) private Integer age;Max数值类型必须 ≤ 指定值Max(120) private Integer age;DecimalMin数值类型、字符串数字必须 ≥ 指定值适合金额、小数DecimalMin(0.00) private BigDecimal price;DecimalMax数值类型、字符串数字必须 ≤ 指定值DecimalMax(99999.99) private BigDecimal price;Positive数值类型必须大于 0Positive private Integer count;PositiveOrZero数值类型必须 ≥ 0PositiveOrZero private BigDecimal amount;Negative数值类型必须小于 0Negative private Integer loss;NegativeOrZero数值类型必须 ≤ 0NegativeOrZero private BigDecimal change;Digits数值类型限制整数位数和小数位数Digits(integer10, fraction2) private BigDecimal amount;8.3 日期时间校验注解适用类型校验规则用例Past日期时间必须是过去时间Past private LocalDate birthday;PastOrPresent日期时间必须是过去或当前时间PastOrPresent private LocalDate startDate;Future日期时间必须是未来时间Future private LocalDate expireDate;FutureOrPresent日期时间必须是未来或当前时间FutureOrPresent private LocalDateTime endTime;8.4 布尔校验注解适用类型校验规则用例AssertTrueBoolean必须为trueAssertTrue private Boolean agreed;AssertFalseBoolean必须为falseAssertFalse private Boolean deleted;

相关新闻

Window 11无法访问网络共享盘,错误码 1208

Window 11无法访问网络共享盘,错误码 1208

访问网络共享盘时提示无法访问方法一:修改注册表 Windows 11 家庭版没有组策略编辑器,最直接的方法是修改注册表。 打开注册表编辑器:按 Win R 键,输入 regedit,点击确定。定位路径:在顶部地址栏复制并粘贴…

2026/10/14 3:32:36 阅读更多 →
精华贴分享|美联储加息、降息、不变,对大饼到底有没有影响?

精华贴分享|美联储加息、降息、不变,对大饼到底有没有影响?

本文来源于量化小论坛策略分享会板块精华帖,作者为羽昕,发布于2026年9月15日。以下为精华帖正文:前言:我经常在群里听老板说,美联储又要开会了,什么大的要来了。听着我还是云里雾里,只知道会有很…

2026/10/14 3:32:36 阅读更多 →
算法(71):suffix array(下:算法具体)

算法(71):suffix array(下:算法具体)

第 59 页:KWIC 的后缀排序解决方案预处理:对文本进行后缀排序。查询:二分查找查询词;然后扫描直到不匹配。图示:在排序后的后缀数组中,二分查找 "search",找到一片连续区域。物理含义…

2026/10/14 3:32:36 阅读更多 →

最新新闻

AI工程师核心能力拆解:从零实现、数据敏感度与实验管理实战路径

AI工程师核心能力拆解:从零实现、数据敏感度与实验管理实战路径

1. 这个项目到底在解决什么问题第一次看到“andrej-karpathy-skills”这个标题,很多人会以为这是某个开源代码库或者工具包。实际上,它更像是一份能力清单——把一位顶级AI研究者兼教育者身上那些可迁移、可练习、可复用的技能拆解出来,形成一…

2026/10/14 4:17:49 阅读更多 →
加工精度与加工误差核心考点梳理:从误差源到控制措施

加工精度与加工误差核心考点梳理:从误差源到控制措施

加工精度与加工误差这部分内容,在机械制造的研究生入学考试里几乎是每年必考的硬骨头。很多同学复习到这里会觉得特别琐碎——概念多、公式杂、影响因素一个接一个,背了后面忘前面。我自己当年备考的时候也在这个章节上栽过跟头,后来把整章的…

2026/10/14 4:17:49 阅读更多 →
适合老人小孩的重庆传统麻花米花糖,龙门浩强哥土特产店选购指南

适合老人小孩的重庆传统麻花米花糖,龙门浩强哥土特产店选购指南

为老人儿童挑选重庆传统点心的关键维度在寻找适合老人小孩吃的重庆传统麻花和米花糖时,首要关注的并非花哨的包装,而是食品本身的质地与配料。对于牙口较弱的老人和处于换牙期或咀嚼力尚未完全发育的儿童而言,酥脆度和硬度是核心筛选指标。传…

2026/10/14 4:17:49 阅读更多 →
PS5存储、备份与外设全攻略:打造顺手的AnyPS5管理方案

PS5存储、备份与外设全攻略:打造顺手的AnyPS5管理方案

用了几年主机,最深的体会是:真正决定体验上限的,不是机器本身,而是你愿不愿意在“周边配套”上花心思。去年我入手PS5之后,头一个月其实过得相当狼狈——游戏装不下、手柄来回换、存档备份靠运气、电视柜下面一堆线理不…

2026/10/14 4:17:49 阅读更多 →
FBX导入实战指南:从单位坐标到骨骼动画的避坑手册

FBX导入实战指南:从单位坐标到骨骼动画的避坑手册

做3D内容的人,无论是建模、动画还是游戏开发,几乎每天都在跟“导入fbx”这四个字打交道。它看起来是软件里一个再普通不过的按钮,但实际用起来,从模型变形、骨骼错乱,再到材质变紫、动画抖动,各种幺蛾子层出…

2026/10/14 4:17:49 阅读更多 →
Hadoop网站日志分析实战:MapReduce统计PV、UV与热门URL

Hadoop网站日志分析实战:MapReduce统计PV、UV与热门URL

简介:这份资源是面向大数据与人工智能方向学习者、开发者的一份Hadoop实战项目包,聚焦网站日志的分布式处理与分析。它通过MapReduce编程模型演示如何从海量访问记录中挖掘用户行为、访问模式与服务器性能等关键信息,适合具备一定Java与Hadoo…

2026/10/14 4:16:49 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →