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

Spring Boot 4自定义异常处理:如何保留默认ErrorAttributes生成统一响应?

问题

我需要处理自定义异常,具体需求如下:

  • 保留默认错误响应的结构(属性)并添加错误信息,希望无论异常是否被自定义处理器处理,都生成相同的JSON响应(未处理异常仍使用默认的ErrorAttributes响应);
  • 不想在每个处理器中手动构建响应(比如手动填充Map,担心无法与ErrorAttributes保持同步)。

我尝试了如下代码,但Spring无法注入ErrorAttributes,报错信息如下:

import org.springframework.boot.webmvc.error.ErrorAttributes;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(InvalidTransferException.class)
    public ResponseEntity<ErrorAttributes> handle(ErrorAttributes errorAttributes) {
        return ResponseEntity.unprocessableContent().body(errorAttributes);
    }
}
java.lang.IllegalStateException: Could not resolve parameter [0] in public org.springframework.http.ResponseEntity<org.springframework.boot.webmvc.error.ErrorAttributes> com.example.em_card_service.exception.GlobalExceptionHandler.handle(org.springframework.boot.webmvc.error.ErrorAttributes): No suitable resolver
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:221) ~[spring-web-7.0.7.jar:7.0.7]

期望得到的错误响应JSON结构如下:

{
  "timestamp": "2026-05-15T15:55:24.553Z",
  "status": 422,
  "error": "Unprocessable Content",
  "path": "/api/cards/transfer",
  "message": "Cannot perform transfer to the same card"
}

(使用Spring Boot 4)

解决方案

问题根源

你之前的代码报错是因为ErrorAttributes不能直接作为@ExceptionHandler方法的参数,Spring没有对应的参数解析器支持这种注入方式,必须通过类级别的依赖注入获取实例。

方案1:注入ErrorAttributes构建统一响应

通过构造函数注入ErrorAttributes,利用它获取默认的错误属性Map,再添加自定义异常信息,既保留默认结构又避免手动维护字段:

import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    private final ErrorAttributes errorAttributes;

    // 构造函数注入ErrorAttributes(Spring 4推荐构造函数注入)
    public GlobalExceptionHandler(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    @ExceptionHandler(InvalidTransferException.class)
    public ResponseEntity<Map<String, Object>> handleInvalidTransferException(InvalidTransferException ex, WebRequest request) {
        // 获取默认错误属性(包含timestamp、status、error、path等默认字段)
        Map<String, Object> errorResponse = errorAttributes.getErrorAttributes(
                request,
                ErrorAttributeOptions.defaults() // 可按需调整,比如添加栈信息用ErrorAttributeOptions.of(Include.STACK_TRACE)
        );
        // 替换为自定义异常消息
        errorResponse.put("message", ex.getMessage());
        // 设置对应HTTP状态码
        return ResponseEntity.unprocessableContent().body(errorResponse);
    }
}

方案2:自定义ErrorAttributes实现全局统一处理

如果需要对所有异常(包括未处理的)都保持响应结构一致,推荐自定义ErrorAttributes,这样无需在每个异常处理器中重复构建响应:

第一步:自定义ErrorAttributes

import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
        // 获取默认错误属性
        Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, options);
        Throwable error = getError(webRequest);

        // 处理自定义异常,设置对应的消息和状态码
        if (error instanceof InvalidTransferException) {
            errorAttributes.put("message", error.getMessage());
            errorAttributes.put("status", 422);
            errorAttributes.put("error", "Unprocessable Content");
        }
        // 可扩展其他自定义异常的处理逻辑
        return errorAttributes;
    }
}

第二步:简化异常处理器(仅指定状态码)

此时异常处理器只需返回对应HTTP状态码,响应体由自定义的ErrorAttributes自动生成:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(InvalidTransferException.class)
    public ResponseEntity<Void> handleInvalidTransferException() {
        return ResponseEntity.unprocessableContent().build();
    }
}

方案优势

  • 两种方案都保留了Spring Boot默认的错误响应结构,无需手动维护timestamp、path等字段,避免与默认实现脱节;
  • 方案2更适合全局统一管理所有异常的响应格式,未处理的异常也会自动使用相同结构返回。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 01:43:12