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

Spring MVC Rest Controller中实体校验消息不显示及错误返回HTML而非JSON问题排查

问题分析与解决方案

你遇到的问题是Spring MVC REST接口在参数校验失败时,返回HTML错误页面而非JSON格式的自定义校验消息,核心原因是Spring MVC默认的异常处理机制没有针对REST场景做适配,没有捕获并处理参数校验抛出的异常,而是直接转发到错误页面。下面是具体的原因解释和解决步骤:


一、核心原因

当你使用@Valid注解校验请求体时,如果校验失败,Spring会抛出MethodArgumentNotValidException异常;如果请求体为null,则会抛出HttpMessageNotReadableException。Spring MVC默认的异常解析器会将这些异常映射到错误页面(比如/error),返回HTML格式响应,而不会自动返回包含自定义校验消息的JSON。


二、解决办法

1. 添加全局异常处理器(推荐方案)

创建一个全局异常处理类,专门捕获校验相关的异常,提取自定义错误消息并封装成JSON响应返回。这种方式可以统一处理所有REST接口的校验异常,复用性强。

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.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.http.converter.HttpMessageNotReadableException;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalRestExceptionHandler {

    // 处理参数校验失败的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) {
        Map<String, String> errorMap = new HashMap<>();
        // 提取每个字段的自定义校验消息
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errorMap.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST);
    }

    // 处理请求体为null的异常
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<String> handleNullRequestBody(HttpMessageNotReadableException ex) {
        return new ResponseEntity<>("Request body cannot be null or empty", HttpStatus.BAD_REQUEST);
    }
}

2. 验证依赖完整性(确保已有)

你的pom.xml已经包含了必要的依赖,无需额外添加:

  • hibernate-validator:提供JSR-380校验规范的实现,支持@NotBlank、@Size等注解
  • jackson-databind:负责JSON的序列化与反序列化,确保响应能以JSON格式返回

如果后续出现JSON序列化问题,可以检查版本兼容性(你的Spring 5.2.8.RELEASE与Jackson 2.9.9.2、Hibernate Validator 6.2.0.Final是兼容的)。

3. 可选:手动处理校验错误(不推荐)

如果你不想用全局异常处理器,也可以在控制器方法中添加BindingResult参数手动处理校验错误,但这种方式需要在每个校验方法中重复编写逻辑:

@PostMapping(value = "", produces="application/json")
public ResponseEntity<?> createNewProject(@Valid @RequestBody Project project, BindingResult result){
    // 手动检查校验结果
    if(result.hasErrors()){
        Map<String, String> errorMap = new HashMap<>();
        result.getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errorMap.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST);
    }
    Project proj1 = projectService.saveOrUpdate(project);
    return new ResponseEntity<Project>(proj1, HttpStatus.CREATED);
}

三、测试验证

完成配置后,用Postman发送无效请求(比如projectName为空、projectIdentifier长度不符合要求),会收到如下JSON格式的响应:

{
    "projectName": "Project name cannot be blank",
    "projectIdentifier": "Please use 4-5 character identifier"
}

发送null请求体时,会收到:

"Request body cannot be null or empty"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:17:36