validationexception 是开发者自定义的校验异常,用于统一处理参数校验失败,继承 runtimeexception,携带 errorcode、field、message 等字段;需全局捕获 methodargumentnotvalidexception 并转换为结构化 400 响应,区分于业务异常 bizexception。

在 Java Web 接口中,ValidationException 不是 Spring 或标准 JDK 提供的内置异常,而是需要开发者自行封装的自定义校验异常类型。它的核心目标是:统一拦截参数校验失败(如 @Valid、@NotBlank 等注解触发的约束违反),并以结构化、可读、易处理的方式返回给前端。
定义 ValidationException 自定义异常类
继承 RuntimeException,便于非强制捕获,同时携带校验错误详情(如字段名、错误信息、错误码):
- 建议包含
errorCode(如"VALIDATION_FAILED")、field(出错字段)、message(用户友好提示)、rejectedValue(非法值)等字段 - 提供多个构造方法,支持快速构建单字段或批量错误场景
- 避免直接暴露技术细节(如 Hibernate Validator 的 ConstraintViolation),对外只暴露业务语义清晰的信息
全局统一捕获 MethodArgumentNotValidException
Spring Boot 中使用 @Valid 或 @Validated 校验 Controller 入参时,失败会抛出 MethodArgumentNotValidException。需用 @ControllerAdvice 拦截并转换为 ValidationException:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 提取
BindingResult中所有FieldError,逐个构造ValidationException或其包装体(如ValidationError列表) - 推荐封装一个
ValidationError对象(含 field、message、code),再整体放入响应体,而非只抛一个异常 - 不要在全局异常处理器中直接 throw 新的
ValidationException,而是构造统一响应结果(如Result<void>.fail(...)</void>)并返回 HTTP 400
响应体结构设计与状态码约定
前端需要明确知道这是参数问题,所以 HTTP 状态码应为 400 Bad Request,响应体格式要一致:
- 顶层字段建议包含:
code(业务错误码,如40001)、message(总提示,如“请求参数校验失败”)、details(List) -
ValidationError示例:{"field":"email","message":"邮箱格式不正确","code":"INVALID_EMAIL"} - 避免把整个
ConstraintViolation堆栈或国际化 key(如NotBlank.user.name)直接返回给前端
进阶:集成分组校验与自定义约束注解
当接口需区分创建/更新等不同校验场景时,可结合校验分组(@Validated({CreateGroup.class})):
- 自定义注解(如
@Mobile)应配套实现ConstraintValidator,并在验证失败时主动抛出带上下文的ValidationException或填充到BindingResult - 全局异常处理器需兼容分组导致的多条规则触发,确保所有违规项都被收集,不因某一条失败就中断后续校验
- 若业务逻辑中手动校验(如 service 层),可用
Validator#validate()获取Set<constraintviolation></constraintviolation>,再转为统一错误结构
不复杂但容易忽略的是异常语义边界——ValidationException 只负责“参数不对”,不处理“业务规则不满足”(如余额不足),后者应使用独立的 BizException。分清这两类,接口错误反馈才真正清晰可靠。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










