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

Spring Boot中REST服务校验实现及通用@ControllerAdvice错误处理

Spring Boot实现REST服务校验的通用@ControllerAdvice处理方案

我来帮你搞定这个全局校验异常处理的需求,完全贴合你的返回格式要求,一步步来:

第一步:确保基础配置就绪

  • 如果你用的是Spring Boot 2.3及以上版本,得单独引入校验模块依赖(因为这版本把校验组件从web starter里拆分出来了),Maven的话在pom.xml里加:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 然后在你的REST接口里,给DTO参数加上@Valid注解,这样Spring才会触发校验逻辑:
@PostMapping("/users")
public ResponseEntity<UserDTO> createUser(@Valid @RequestBody UserDTO userDTO) {
    // 这里写你的业务逻辑
    return ResponseEntity.ok(userDTO);
}

第二步:实现全局异常处理类

用@ControllerAdvice创建全局异常处理器,专门捕获校验失败抛出的MethodArgumentNotValidException,把错误转换成你要的格式:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@ControllerAdvice
public class GlobalValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<List<Map<String, String>>> handleValidationErrors(MethodArgumentNotValidException ex) {
        // 把所有校验错误转换成[{field: message}]的格式
        List<Map<String, String>> errorList = ex.getBindingResult()
                .getAllErrors()
                .stream()
                .map(error -> {
                    String fieldName = ((FieldError) error).getField();
                    String errorMsg = getCustomMessage(error.getCode(), fieldName);
                    return Map.of(fieldName, errorMsg);
                })
                .collect(Collectors.toList());
        
        // 返回422状态码和错误列表
        return new ResponseEntity<>(errorList, HttpStatus.UNPROCESSABLE_ENTITY);
    }

    // 自定义错误消息,也可以用配置文件管理(后面会说)
    private String getCustomMessage(String errorCode, String field) {
        return switch (errorCode) {
            case "Email" -> "it's not a valid mail";
            case "NotEmpty" -> "required field";
            // 如果phone传了但长度不符合@Size要求,也可以单独处理
            case "Size" -> field.equals("phone") ? "required field" : "invalid length";
            default -> errorCode;
        };
    }
}

更优雅的消息管理方式(可选)

如果不想在代码里硬编码消息,也可以用ValidationMessages.properties配置文件来统一管理,放在src/main/resources目录下:

# 对应@NotEmpty注解的提示语
javax.validation.constraints.NotEmpty.message=required field
# 对应@Email注解的提示语
javax.validation.constraints.Email.message=it's not a valid mail
# 对应phone的@Size注解提示语(因为要求固定11位,没传时其实先触发NotEmpty,传错长度时用这个)
javax.validation.constraints.Size.message=required field

这时候上面的getCustomMessage方法就可以删掉,直接用error.getDefaultMessage()即可:

.map(error -> {
    String fieldName = ((FieldError) error).getField();
    String errorMsg = error.getDefaultMessage();
    return Map.of(fieldName, errorMsg);
})

测试效果

当你发送请求:

{ "name": "John Lennon", "email": "jonnlennon" }

系统会触发两个校验错误:

  1. email不符合@Email规则,返回"it's not a valid mail"
  2. phone未传,触发@NotEmpty规则,返回"required field"

最终返回的响应完全符合你的要求:

[{ "email": "it's not a valid mail" }, { "phone": "required field" }]

状态码为422(UNPROCESSABLE_ENTITY)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:25:06