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

(Spring)Spring Boot 中 @Valid 与全局异常处理器的联系详解

在实际项目开发中,参数校验是保障接口安全性与数据正确性的第一道防线。而在 Spring Boot 中,我们通常会用 @Valid(或 @Validated)来触发校验,再结合全局异常处理器 @RestControllerAdvice 来实现统一的异常返回。

很多同学知道它们可以一起工作,但并不清楚 它们是怎么联系起来的。本文将带你从底层原理出发,彻底搞懂它们的配合机制。


一、@Valid 的作用

@ValidJSR-303(Java Bean Validation) 规范中的注解,用于触发数据校验。
它一般用在 Controller 的方法参数上,例如:

@PostMapping("/register")public ResponseResult<Void> register(@Valid @RequestBody UserDTO userDTO) {// 业务逻辑... return ResponseResult.success(); 
}

DTO 示例:

@Data
public class UserDTO {@NotBlank(message = "用户名不能为空")private String username;@Email(message = "邮箱格式不正确")private String email;@Size(min = 6, message = "密码长度至少6位")private String password;
}

当请求中传入非法参数时,Spring 会自动执行校验,并在不符合规则时抛出异常。


二、触发校验失败会发生什么?

@Valid 检测到参数不合法时,Spring 不会让 Controller 方法继续执行,而是抛出一个异常:

MethodArgumentNotValidException

举个例子,前端传入:


{ 
"username": "", 
"email": "abc", 
"password": "123"
}

Spring 框架内部的校验逻辑检测失败后,会抛出:

throw new MethodArgumentNotValidException(...)

此时方法体还没执行,异常会被直接上抛到 Spring MVC 的核心调度器 DispatcherServlet


三、Spring 是怎么“找到”全局异常处理器的?

Spring MVC 的核心组件 DispatcherServlet 会捕获 Controller 执行过程中的所有异常。
内部会执行类似以下逻辑(伪代码):

try {handlerAdapter.handle(request, response, handler);
} catch (Exception ex) {processDispatchResult(request, response, handler, mv, ex);
}

接着,它会去找有没有能处理这种异常的处理器:

  1. 当前 Controller 类里有没有定义:

    @ExceptionHandler(MethodArgumentNotValidException.class)

  2. 如果没有,再去扫描项目中所有带有:

    @ControllerAdvice 或 @RestControllerAdvice
    

于是,它就发现了你的全局异常处理器:

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseResult<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {String message = e.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(", "));log.warn("参数校验失败: {}", message);return ResponseResult.error(message);}
}

四、全局异常处理器如何工作?

@RestControllerAdvice 可以理解为在所有 Controller 上方挂了一张“异常网”。
一旦某个接口抛出异常,Spring 会自动把异常交给这张网中的 @ExceptionHandler 方法处理。

上面的代码中,我们通过 getFieldErrors() 提取所有字段的错误信息,然后统一返回一个结构化的响应对象:

{"code": 400,"msg": "用户名不能为空, 邮箱格式不正确, 密码长度至少6位","data": null
}

相比 Spring 默认返回的 HTML 错误页面,这种写法对前后端分离项目更加友好。


五、@Valid 与 @RestControllerAdvice 的工作链路总结

整个链路可以概括为:

@Valid 参数校验↓
校验失败抛出 MethodArgumentNotValidException↓
异常上抛至 DispatcherServlet↓
Spring MVC 寻找 @ExceptionHandler 处理方法↓
匹配到 GlobalExceptionHandler 中的处理逻辑↓
返回统一格式的 ResponseResult JSON 响应

一句话总结:

@Valid 负责“发现错误”,
@RestControllerAdvice 负责“优雅处理错误”。


六、总结

  • @Valid / @Validated 用于触发参数校验。

  • 校验失败后,Spring 自动抛出异常。

  • @RestControllerAdvice + @ExceptionHandler 捕获异常并返回统一格式。

  • 无需手动调用,两者通过 Spring MVC 的异常机制自动关联。


七、推荐实践

  1. 统一返回结构(如 ResponseResult

  2. 日志中记录详细的异常信息,方便定位问题

  3. 对常见异常(校验异常、登录异常、业务异常)分别编写处理方法

  4. 保持响应格式一致,前端可统一处理


结语:

很多时候,优秀的后端并不体现在写了多少业务逻辑,而在于“出错时的优雅”。
@Valid 与全局异常处理器的配合,就是后端代码优雅性的象征。

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

相关文章:

  • 数据库数据类型,数据值类型,字符串类型,日期类型详解
  • 怎么写网站规划方案买链接做网站 利润高吗
  • SAP MM物料主数据锁定及解锁接口分享
  • [FSCalendar] 可定制的iOS日历组件 | docs | Interface Builder
  • 中兴B860AV5.1-M2/B860AV5.2M_安卓9_S905L3SB_支持外置WIFI_线刷固件包
  • AI 模型部署体系全景:从 PyTorch 到 RKNN 的嵌入式类比解析
  • 全球汽车紧固件产业进入关键转型期,中国供应链加速融入世界市场
  • 17网站一起做网店下载自动发卡网站建设
  • PHP 类型比较
  • oracle:To_char
  • MySQL 数据库核心操作全解析:从创建到备份与连接管理
  • 环境函数 SYS_CONTEXT 在 DM8 与 Oracle 中的差异
  • 长春怎么做网站重庆网站建设aiyom
  • Linux中的管道与重定向:深入理解两者的本质区别
  • 上传OSS服务器图片文件视频(使用elemenplus上传组件)
  • 全面适配iOS 26液态玻璃,基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.2发布
  • 【Kubernetes】常见面试题汇总(二十五)
  • 阿里云渠道商:哪些方法能给服务器加速?
  • 华为USG 6320之配置外网访问服务器NAT映射和NAT回流
  • 网站开发业务介绍深圳网站搭建找哪里
  • 常见的网站模板类型有哪些,新手该如何选择最合适的?
  • 【Linux】基础IO(一)Linux 文件操作从入门到实践:系统调用、文件描述符、重定向,为自定义Shell添加重定向
  • Docker 深度解析:从虚拟化到新一代应用构建、运行与交付
  • 企业网站建设网站有哪些建企业网站用什么源码
  • 复制了一个vue的项目然后再这个基础上修改。可是通过npm run dev运行之前的老项目,发现运行的竟然是拷贝后的项目。为什么会这样?
  • 【Prisma】Prisma 命令大全(Node / NestJS 通用)
  • 十月连环效应:宏观叙事与链上机会的临界点
  • 第六部分:VTK进阶(第161章 多渲染Pass组合)
  • 三相变流器矢量控制及参数设计系列(2):PWM原理
  • 网络层IP协议详解:互联网的灵魂所在