李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 读书观影
  • 系列
  • AI工具集
  • 论坛
  • 友圈
    • 友链
    • 朋友圈
    • 游客中心
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于本站
    • Now
    • 每日心情
    • 网站地图
    • 网站统计
    • 赞助
  • 星球穿梭
  • 🚇开往
静亦定 动亦定
惟坚韧者始能遂其志
  1. 首页
  2. 原创
  3. 正文

@Valid 和 @Validated 的区别

2025年5月23日 254 0 2
本文最后更新于 2025年5月23日,距今已 533 天,其中的信息可能已经发生变化,请注意甄别。

前言

参数校验是保证程序健壮性的重要环节,前端校验为用户体验,后端校验为系统安全。Spring Boot 中常用 @Valid 和 @Validated 实现参数校验,本文将详细解析两者的区别、用法及代码示例。

一、@Valid 注解

1. 功能与依赖

  • 标准规范:属于 Java EE 标准注解(JSR 303 规范),用于触发参数合法性校验。
  • 依赖引入:
    • Spring Boot 项目:已包含在 spring-boot-starter-web 中,无需额外引入。
    • 非 Spring Boot 项目:需手动添加 javax.validation 和 hibernate-validator 依赖。
<!-- 非Spring Boot项目依赖 -->  
<dependency>  
    <groupId>javax.validation</groupId>  
    <artifactId>validation-api</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.hibernate</groupId>  
    <artifactId>hibernate-validator</artifactId>  
</dependency>  

2. 使用场景

  • 适用位置:方法参数、构造函数、成员属性(field)、方法返回值。
  • 核心功能:支持嵌套校验(对对象中的属性值,甚至嵌套对象进行校验)。
  • 代码示例:

    // 实体类  
    @Data  
    public class SysUser {  
      @NotBlank(message = "姓名不能为空")  
      @Length(max = 10, message = "名称不能超过{max}字符")  
      private String name;  
    
      @NotNull(message = "年龄不能为空")  
      @Range(min = 1, max = 100, message = "年龄范围为{min}到{max}岁")  
      private Integer age;  
    }  
    // 控制器  
    @RestController  
    @RequestMapping("/sysUser")  
    public class SysUserController {  
      @PostMapping("/add")  
      public String addUser(@RequestBody @Valid SysUser sysUser, BindingResult bindingResult) {  
          if (bindingResult.hasErrors()) {  
              return bindingResult.getAllErrors().get(0).getDefaultMessage(); // 返回第一条错误信息  
          }  
          return "操作成功!";  
      }  
    }  

    说明:需通过 BindingResult 手动捕获校验结果,若不处理错误,程序不会中断执行。

二、@Validated 注解

1. 功能与定位

  • Spring 专属:Spring 框架特有的注解,是 @Valid 的增强版,支持分组验证。
  • 无嵌套校验:仅能对单一对象进行校验,无法递归验证嵌套对象。

2. 使用场景

  • 适用位置:类、方法、方法参数(不能用于成员属性)。
  • 分组验证:针对同一对象的不同操作(如新增、更新),设置不同的校验规则。

    // 分组接口  
    public interface CreationGroup {} // 新增分组  
    public interface UpdateGroup {} // 更新分组  
    // 实体类(分组校验示例)  
    @Data  
    public class SysUser {  
      @NotNull(message = "更新时ID不能为空", groups = UpdateGroup.class)  
      private String id;  
    
      @NotBlank(message = "名字不能为空", groups = {CreationGroup.class, UpdateGroup.class})  
      @Size(min = 6, max = 12, message = "名字长度在6-12之间")  
      private String name;  
    }  
    // 控制器(分组校验应用)  
    @RestController  
    public class SysUserController {  
      @PostMapping("/insert")  
      public String insertUser(@Validated(CreationGroup.class) @RequestBody SysUser sysUser, BindingResult bindingResult) {  
          if (bindingResult.hasErrors()) {  
              return "插入失败:" + bindingResult.getFieldError().getDefaultMessage();  
          }  
          return "插入成功";  
      }  
    
      @PostMapping("/update")  
      public String updateUser(@Validated(UpdateGroup.class) @RequestBody SysUser sysUser, BindingResult bindingResult) {  
          // 同上逻辑  
      }  
    }  

3. 全局异常处理

  • 自动抛异常:使用 @Validated 时,若校验失败,程序会自动抛出 MethodArgumentNotValidException。
  • 统一捕获:通过 @RestControllerAdvice 全局捕获异常,返回友好提示。
    @RestControllerAdvice  
    public class ValidatedExceptionHandler {  
      @ExceptionHandler(MethodArgumentNotValidException.class)  
      @ResponseBody  
      @ResponseStatus(HttpStatus.BAD_REQUEST)  
      public Result handleValidationException(MethodArgumentNotValidException ex) {  
          String errorMessage = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();  
          return Result.error("参数校验失败:" + errorMessage);  
      }  
    }  

三、核心区别对比

维度 @Valid @Validated
所属框架 Java EE(JSR 303) Spring 框架
嵌套校验 支持(可校验嵌套对象) 不支持
分组验证 不支持 支持(通过 groups 参数定义分组)
适用位置 方法、构造函数、参数、成员属性 类、方法、参数(不能用于成员属性)
校验结果处理 需手动通过 BindingResult 捕获 自动抛出异常,需全局捕获处理
代码简洁性 需显式处理错误结果 自动中断流程,代码更简洁

四、参数校验常用注解

1. 值校验

注解 说明 示例
@Null 必须为 null @Null(message = "人数必须为null")
@NotNull 不能为 null @NotNull(message = "人数不能为空")
@NotBlank 字符串非空(至少一个非空格字符) @NotBlank(message = "姓名不能为空")
@NotEmpty 集合/数组非空 @NotEmpty(message = "组织部门不能为空")
@Positive 必须为正数 @Positive(message = "金额必须为正数")

2. 范围校验

注解 说明 示例
@Min 最小值约束 @Min(value = 18, message = "年龄≥18")
@Max 最大值约束 @Max(value = 120, message = "年龄≤120")
@Range 范围约束(min/max) @Range(min = 18, max = 80, message = "年龄范围")
@Past 必须为过去时间 @Past(message = "日期必须为过去")

3. 长度校验

注解 说明 示例
@Size 集合/数组长度约束 @Size(min = 7, max = 11, message = "长度7-11")
@Length 字符串长度约束 @Length(min = 6, max = 12, message = "姓名长度")

4. 格式校验

注解 说明 示例
@Pattern 正则匹配 @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
@Email 邮箱格式校验 @Email(message = "请输入有效邮箱")
@URL URL 格式校验 @URL(message = "无效的URL地址")

五、总结

  • 选择建议:
    • 需要嵌套校验(如对象中包含子对象)时,使用 @Valid。
    • 需要分组验证(如不同业务场景执行不同校验规则)时,使用 @Validated。
  • 最佳实践:
    • 统一使用 @Validated 简化代码,通过全局异常处理统一返回错误信息。
    • 复杂校验场景结合分组验证,提高代码可维护性。

掌握 @Valid 和 @Validated 的区别,能更灵活地实现参数校验,保障系统数据的完整性和安全性。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
分享到

@Valid 和 @Validated 的区别

也可使用浏览器菜单中的「分享」功能

微信扫一扫分享

标签: JAVA SpringBoot 安全
最后更新:2025年5月23日
相关文章
  • jmap命令(jdk1.8)2020年9月27日
  • 阿里巴巴《Java开发手册》下载2019年6月28日
  • JAVA设计模式-抽象工厂模式2020年2月18日
  • ZGC介绍2025年2月15日
  • JVM详细参数说明2020年7月27日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

  • lzjLv 1

    您好,请问您的自定义域名邮箱mailme@lifengdi.com是怎么实现的,自建的吗?

    WindowsWindowsChrome 136.0.0.0Chrome 136.0.0.0中国中国-北京
    2025年5月23日
    00 回复
    • 李锋镝博主

      @lzj 用的是阿里云的企业邮箱。 :8:

      macOSmacOSChrome 136.0.0.0Chrome 136.0.0.0中国中国-北京
      2025年5月23日
      00 回复
  • 雨打梨花深闭门,忘了青春,误了青春。
    赏心乐事共谁论?花下销魂,月下销魂。
    愁聚眉峰尽日颦,千点啼痕,万点啼痕。
    晓看天色暮看云,行也思君,坐也思君。

    听点儿音乐吧 朋友~
    文章目录
    最新 热点 随机
    最新 热点 随机
    给服务器加了WAF 又一个逆天改命的人:小小徐 AI的生成能力等于生产力吗? NGINX严重漏洞(CVE-2026-15176、CVE-2026-93479、CVE-2026-97205) Kratos-plus v1.1.27更新说明 php2shell远程执行漏洞修复(CVE-2026-109618 和 CVE-2026-109619)
    给主题增加了游客中心功能心气没了,干什么都不得劲我觉得是时候公布我的导航网站了给服务器加了WAF游本昌去世关于主题加载速度优化的一点儿小演进
    前端开发者进阶AI Agent开发:全栈知识体系与实战指南 学习算法必备知识:时间复杂度与空间复杂度的计算 Java设计模式:状态模式 英伟达 H100 是啥,到底好在哪? 分代ZGC这么牛?底层原理是什么? jstat命令使用(JDK1.8)
    最近评论
    fairy 发布于 1 天前(11月06日) 机器人快来我这里吧!
    李锋镝 发布于 1 天前(11月06日) 都是机器人,防不住
    李锋镝 发布于 1 天前(11月06日) 是的,太烦了
    李锋镝 发布于 1 天前(11月06日) 可以同一台服务器
    fairy 发布于 1 天前(11月06日) 这流量,好厉害啊。我一年都没那么多
    标签聚合
    Theme SpringBoot IDEA Spring JVM ElasticSearch 分布式 AI编程 数据库 AI JAVA WordPress Claude 架构 K8s SQL Redis MySQL 日常 多线程
    友情链接
    • 彬红茶日记
    • 九仞之行
    • 搬砖日记
    • 韩情脉脉
    • 知向前端
    • 哥斯拉
    • 韩小韩博客
    • 皮皮社
    • 刘永博客
    • 志文工作室
    • sssr7844的博客
    • lijie blog
    • Serendipity
    • 懋和道人
    • 老张博客
    • 林羽凡
    • 瓦匠个人小站
    • Mr.Sun的博客
    • Honesty

    COPYRIGHT © 2016-2026 lifengdi.com. ALL RIGHTS RESERVED.

    lifengdi.com 十年之约虫洞

    Domain age badge for lifengdi.com

    Theme Kratos-plus By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号