You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot @Valid校验DTO失败时抛出的实际异常类型是什么

参数校验全局异常拦截失效问题

问题描述

  • 提交不符合校验规则的DTO请求时,全局异常处理器中配置的@ExceptionHandler(ValidationException.class)方法未触发,仅兜底的Exception类型处理器可以捕获该异常,需要明确异常实际类型以编写精准匹配的处理逻辑。
  • 关闭通用异常处理器后,接口返回默认400错误响应:
    异常响应截图

关联代码

DTO定义

public class BookDto {
    
    @NotBlank(message = "Name of the book cannot be empty!")
    @Size(min = 4, max = 30, message = "Name of the book must be between 4 and 30 characters long!")
    public String name;

    @NotBlank(message = "Author of the book cannot be empty!")
    @Size(min = 4, max = 35, message = "Author of the book must be between 5 and 35 characters long!")
    public String author;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    public LocalDate publicationYear;

    @NotNull(message = "Pages of the book cannot be null!")
    @Digits(integer = 4, fraction = 0)
    public int pagesNumber;

    @NotBlank(message = "Publisher of the book cannot be empty!")
    @Size(min = 4, max = 30, message = "Publisher of the book must be between 4 and 30 characters long!")
    public String publisher;

}

全局异常处理器定义

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    protected ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(ResourceWasDeletedException.class)
    protected ResponseEntity<MyGlobalExceptionHandler> handleDeleteException() {
        return new ResponseEntity<>(new MyGlobalExceptionHandler("This book was deleted!"), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<?> handleValidationException(ValidationException exception, WebRequest webRequest) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), exception.getMessage(), webRequest.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }

    /*    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> globalExceptionHandler(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }*/

    @Data
    @AllArgsConstructor
    private static class MyGlobalExceptionHandler {
        private String message;
    }
}

接口定义

@PostMapping("/books")
@ResponseStatus(HttpStatus.CREATED)
public BookDto createBook(@Valid @RequestBody BookDto requestForSave){
    var book = converter.getMapperFacade().map(requestForSave, Book.class);
    log.debug("Book={}", book);
    var bookDto = converter.toDto((Book) bookService.create(book));
    log.debug("Book={}", bookDto);
    return bookDto;
}

问题根因

该场景下@RequestBody标注的请求体参数校验失败时,Spring MVC抛出的异常类型为**org.springframework.web.bind.MethodArgumentNotValidException**,并非ValidationException,因此原有校验异常处理器无法匹配触发。

补充说明:ValidationException的子类ConstraintViolationException仅会在@RequestParam、@PathVariable这类非请求体参数校验失败时抛出,无法覆盖@RequestBody的校验场景。

修复方案

在全局异常处理器中新增MethodArgumentNotValidException类型的异常处理方法即可,示例代码如下:

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleMethodArgInvalidException(MethodArgumentNotValidException ex, WebRequest webRequest) {
    // 提取所有字段校验错误信息
    List<String> errMsgs = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.toList());
    ErrorDetails errorDetails = new ErrorDetails(new Date(), String.join("; ", errMsgs), webRequest.getDescription(false));
    return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

注意:Spring Boot 2.3及以上版本需要手动引入spring-boot-starter-validation依赖,校验相关逻辑才会正常生效。

内容的提问来源于stack exchange,提问作者iank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:24:28