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

如何优雅捕获ResponseEntityExceptionHandler中定义的所有标准Spring MVC异常(无需逐个重写处理方法)

优雅接管Spring MVC标准异常并返回统一JSON响应

我之前也碰到过一模一样的需求——不想逐个重写ResponseEntityExceptionHandler里的各种异常处理方法,但又要把它覆盖的所有Spring MVC标准异常都用自定义格式返回。这里有个非常简洁的解决方案,只需要两步就能搞定:

1. 定义标准错误响应DTO

首先先封装一个统一的错误响应类,包含你需要的状态码、错误信息、时间戳等字段:

import java.time.LocalDateTime;

public class StandardErrorResponse {
    private int status;
    private String message;
    private LocalDateTime timestamp;

    public StandardErrorResponse(int status, String message, LocalDateTime timestamp) {
        this.status = status;
        this.message = message;
        this.timestamp = timestamp;
    }

    // 生成getter方法(JSON序列化需要)
    public int getStatus() { return status; }
    public String getMessage() { return message; }
    public LocalDateTime getTimestamp() { return timestamp; }
}

2. 继承ResponseEntityExceptionHandler并重写核心方法

自定义全局异常处理器,继承ResponseEntityExceptionHandler,然后重写它的handleExceptionInternal方法——这个方法是所有Spring MVC标准异常处理流程的最终出口,所有该类捕获的异常最终都会走到这里生成响应:

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.time.LocalDateTime;

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(
            Exception ex, 
            Object body, 
            HttpHeaders headers, 
            HttpStatusCode statusCode, 
            WebRequest request) {
        
        // 构建统一格式的错误响应
        StandardErrorResponse errorResponse = new StandardErrorResponse(
                statusCode.value(),
                // 你可以根据需求自定义异常信息,比如用ex.getMessage()或者固定提示
                ex.getMessage(),
                LocalDateTime.now()
        );
        
        // 返回封装后的响应实体
        return new ResponseEntity<>(errorResponse, headers, statusCode);
    }
}

为什么这方法可行?

ResponseEntityExceptionHandler里标注了@ExceptionHandler的那个handleException方法,内部会根据异常类型分发到对应的具体处理方法(比如handleHttpRequestMethodNotSupported、handleMethodArgumentNotValid等),而这些具体方法最终都会调用handleExceptionInternal来生成最终的ResponseEntity。所以重写这个方法,就能一次性接管所有该类覆盖的异常,统一修改返回格式,完全不需要逐个重写每个异常的处理逻辑。

额外:针对特殊异常自定义处理

如果某个异常需要特殊的错误信息(比如HttpRequestMethodNotSupportedException要告诉用户支持的请求方法),你也可以单独重写对应的处理方法,同时保留统一的响应格式:

@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
        HttpRequestMethodNotSupportedException ex, 
        HttpHeaders headers, 
        HttpStatusCode statusCode, 
        WebRequest request) {
    
    String customMessage = String.format(
            "请求方法不支持:%s,当前接口支持的方法有:%s",
            ex.getMethod(),
            String.join(", ", ex.getSupportedHttpMethods())
    );
    
    StandardErrorResponse errorResponse = new StandardErrorResponse(
            statusCode.value(),
            customMessage,
            LocalDateTime.now()
    );
    
    return new ResponseEntity<>(errorResponse, headers, statusCode);
}

这样既实现了统一格式的目标,又能灵活处理特殊场景,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:23:12