惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
罗磊的独立博客
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
The Register - Security
The Register - Security
J
Java Code Geeks
V2EX - 技术
V2EX - 技术
Vercel News
Vercel News
N
News and Events Feed by Topic
腾讯CDC
P
Proofpoint News Feed
N
News | PayPal Newsroom
www.infosecurity-magazine.com
www.infosecurity-magazine.com
爱范儿
爱范儿
O
OpenAI News
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
Martin Fowler
Martin Fowler
Engineering at Meta
Engineering at Meta
D
Docker
Y
Y Combinator Blog
博客园 - 聂微东
G
Google Developers Blog
S
Security @ Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
阮一峰的网络日志
阮一峰的网络日志
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
CERT Recently Published Vulnerability Notes
I
Intezer
G
GRAHAM CLULEY
有赞技术团队
有赞技术团队
Attack and Defense Labs
Attack and Defense Labs
V
Visual Studio Blog
博客园 - Franky
博客园 - 三生石上(FineUI控件)
W
WeLiveSecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Hugging Face - Blog
Hugging Face - Blog
Scott Helme
Scott Helme
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 最新话题
C
Cybersecurity and Infrastructure Security Agency CISA

李锋镝的博客

LiteLLM 本地代理搭建 Claude-HUD 使用文档 Kratos+ —— Kratos 主题二次开发记录 译文:如何将单体应用拆解为微服务 codebase-memory-mcp 极简完整使用指南 Claude Haiku 4.5、Claude Sonnet 4.6、Claude Opus 4.7 区别以及各自的新特性 SchedulingConfigurer详解 踩坑60+次后,我终于搞懂 Claude Skill 怎么写才会真的触发 Everything Claude Code 详细使用文档 配置Jackson使用字段而不是getter/setter来序列化和反序列化 这个域名注册整整十年了,十年时间,真快啊 Claude Code全维度实战指南:从入门到精通,解锁AI编程新范式 Apollo配置中心中的protalDB的作用是什么 org.apache.ibatis.plugin.Interceptor类详细介绍及使用 岁末 Excel2016右键新建工作表,打开时提示“因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。”的解决办法 wordpress增加说说功能 Java 为什么有这么多 “O”? 别再背线程池的七大参数了,现在面试官都这么问 2024年11月1号 农历十月初一 我的第一个WordPress插件:Dylan Custom Plugin上线了 推荐一款比较养眼的Xshell配色方案 hnswlib installation failed 开工啦~ 阳了... MybatisCodeHelperPro激活 @Async注解的坑 新买的笔记本发货啦…… 这个中秋节感觉过的好累啊 IDEA下载源码报:Cannot connect to the Maven process. Try again later. RocketMQ的push消费方式实现详解 看病难~取药难~~ 笑死、腹肌……根本不可能有腹肌的~~ 居家办公了~ C# 11 的这个新特性,我愿称之最强! IntelliJ IDEA 2020.3.x永久白嫖(Windows/Mac) IDEA无限试用方法【2020.3最新亲测有效】 SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询 UUID太长怎么办?快来试试NanoId 忽然发现,在校大学生可以免费领一年有道云笔记会员~ 醒醒~补个税了 使用itext和freemarker来根据Html模板生成PDF文件,加水印、印章 来来来,用python画一个冰墩墩儿 SpringBoot整合GraphQL入门教程 办理居住证困难重重啊! 妈呀,昨天晚上睡觉做了一晚上的梦,可累死我了 感觉Typecho很简洁啊…… WordPress的自动更新好烦啊 BeanCopier工具类(性能优化工具类) 内存屏障浅析 居住证可算是申请通过了…… 试了下壁挂炉供暖 关于重阳节 居住证签注... Spring Boot 2.x使用PostgreSQL数据库 十一节后开工头一天,修了个耳机…… 玉楼春·尊前拟把归期说 nginx反向代理配置去除前缀 1931→2021! Navicat Premium数据库账号密码解密 百度的索引量数据现在有点儿太夸张了吧? 哇塞~这个小姐姐实在太惊艳了…… 关于8月29号下午博客故障的一些记录 如何形象的描述反应式编程中的背压(Backpressure)机制? 基于Java8的Either类 海琴烟~~~ JMX监控权限认证配置 IntelliJ IDEA 2019.3.3 永久激活 破解[Windows] SpringBoot整合Elasticsearch详细步骤以及代码示例(附源码) SpringBoot整合Elasticsearch游标查询(scroll) GitLab创建新项目,初次提交命令和流程 吐槽下Google浏览器~ 从零搭建Spring Cloud Gateway网关(一) 从零搭建Spring Cloud Gateway网关(二)—— 打印请求响应日志 博客有logo啦 你的答案 数据库事务的一点简单总结 Spring Boot发展史(Spring Boot介绍) 【漫画】戏说外行对程序员的误会有多深 【收藏】从面试官角度观察到的程序员技能瓶颈,同时给出突破瓶颈的建议 Git中.gitignore文件不起作用的解决办法 背影 - 朱自清 jmap命令(jdk1.8) 彻底搞懂mysql日志系统binlog,redolog,undolog 出院了~~~ linux中ftp查看不到文件列表的问题 PHP版本怎么更新啊…… 成语接龙 StarUML4.0破解文件 Java SPI详解 WordPress评论框增加自定义表情 因在公司上不正经网站,我没过试用期… 优化了MYSQL大量写入问题,老板奖励了1000块给我 不慌不忙的坚强(林徽因39段最美文字!) ConcurrentHashMap常用方法源码解析(jdk1.8) 我是如何失去团队掌控的? HBASE填坑日志 关闭apache httpclient4.5 DEBUG日志 使用OpenShift搭建k8s集群 SonarQube Scanner的配置与使用简介
@Valid 和 @Validated 的区别
李锋镝 · 2025-05-23 · via 李锋镝的博客

前言

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

1. 功能与依赖

  • 标准规范:属于 Java EE 标准注解(JSR 303 规范),用于触发参数合法性校验。
  • 依赖引入
    • Spring Boot 项目:已包含在 spring-boot-starter-web 中,无需额外引入。
    • 非 Spring Boot 项目:需手动添加 javax.validationhibernate-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 的区别,能更灵活地实现参数校验,保障系统数据的完整性和安全性。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/article/4420