使用 @controlleradvice 配合 @exceptionhandler 捕获 httpmessagenotreadableexception 即可拦截序列化器异常。该异常通常在 spring mvc 尝试将 http 请求体反序列化为 java 对象时,因 json 格式错误或字段类型不匹配而抛出。通过定义全局异常处理器并指定处理该异常类,可以统一返回友好的错误信息,避免程序崩溃。

如何配置全局异常处理器来拦截反序列化错误
在 Spring Boot 中,只需创建一个被 @RestControllerAdvice 或 @ControllerAdvice 注解的类,并在其中定义一个方法,该方法由 @ExceptionHandler(HttpMessageNotReadableException.class) 修饰。当控制器接收到无法解析的请求体时,Spring 会自动调用此方法。你可以从异常中提取具体的错误原因,例如缺失必填字段或类型转换失败,并将其封装为统一的响应结构返回给客户端。

import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<String> handleBadRequest(HttpMessageNotReadableException ex) {
// 提取具体错误信息,如 Jackson 的报错详情
String message = ex.getMessage();
if (message == null) {
message = "Invalid request body";
}
return ResponseEntity.badRequest().body(message);
}
}
如何处理嵌套对象中的序列化异常
当请求体包含嵌套对象且内部字段出错时,HttpMessageNotReadableException 依然会被触发。此时可以通过检查异常的 cause 链来获取更详细的上下文。例如,如果嵌套对象的某个字段类型不匹配,异常消息中通常会包含路径信息和具体错误描述。开发者可以在异常处理方法中解析这些消息,或者直接使用 ObjectError 机制(如果启用了 Bean Validation)来提供更精确的错误定位。关键在于确保全局处理器能够捕获到最外层的反序列化异常,从而覆盖所有子对象的解析问题。

import com.fasterxml.jackson.databind.JsonMappingException;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class NestedGlobalExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<String> handleNestedError(HttpMessageNotReadableException ex) {
Throwable cause = ex.getCause();
if (cause instanceof JsonMappingException) {
JsonMappingException jme = (JsonMappingException) cause;
String path = jme.getPath().stream()
.map(JsonMappingException.Reference::getFieldName)
.reduce((a, b) -> a + "." + b)
.orElse("root");
return ResponseEntity.badRequest()
.body("Error in field: " + path + ", reason: " + jme.getOriginalMessage());
}
return ResponseEntity.badRequest().body(ex.getMessage());
}
}
当请求体完全为空时会发生什么
如果客户端发送的请求体为空(即 Content-Length 为 0 或无 Body),Spring MVC 的反序列化器通常不会抛出 HttpMessageNotReadableException,而是可能直接传入 null 值给控制器参数,或者在某些配置下抛出 MissingServletRequestParameterException。这取决于控制器方法的参数是否允许为空以及是否使用了 @RequestBody(required=false)。若参数标记为 required=true 且未提供 Body,Spring 可能会先检查参数存在性,若未检测到则抛出其他异常。因此,在处理序列化异常时,需明确区分“空输入”与“无效 JSON”,前者通常由参数校验层处理,后者由反序列化层处理。


















