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

@ControllerAdvice中能否为同一异常配置适配不同请求的多个@ExceptionHandler

问题原因

Spring MVC 的 @ExceptionHandler 注解仅根据异常类型完成匹配映射,不会参考方法入参中除异常外的其他参数类型。你定义的两个方法都声明处理WebServiceContactException类型异常,Spring 启动时无法区分两个方法的映射规则,就会抛出歧义异常。


可行实现方案

方案1:单处理方法兼容多请求类型(最推荐)

直接在同一个异常处理方法中判断请求类型,既满足日志取值需求,也不会出现映射冲突。@ExceptionHandler 方法支持直接注入当前请求的请求体对象,用Object接收后做类型判断即可:

@EnableWebMvc
@ControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(WebServiceContactException.class)
  @ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
  @ResponseBody
  public MyResponse dealWebServiceContactException(WebServiceContactException e, Object request) {
    int errorCode = HttpStatus.PRECONDITION_FAILED.value();
    String functionalId = null;
    // 判断请求类型取值
    if (request instanceof AddRequest addRequest) {
      functionalId = addRequest.getFunctionalId();
    } else if (request instanceof DeleteRequest deleteRequest) {
      functionalId = deleteRequest.getFunctionalId();
    }
    LOGGER.error("Failed to contact service for " + functionalId, e);
    auditTrail.reportFailureInfo(e.getMessage());
    return MyResponse.Builder.newBuilder(errorCode)
            .setDescription(Constants.EXECUTION_FAILED)
            .build();
  }
}

如果你的请求参数不是直接作为请求体传入,也可以注入HttpServletRequest/WebRequest对象,从中获取对应参数值。

方案2:自定义异常携带请求信息

抛出自定义异常时,直接把当前请求对象作为入参传入异常构造方法,处理时直接从异常中取所需字段即可:
首先修改自定义异常类:

public class WebServiceContactException extends RuntimeException {
  private final Object request;

  public WebServiceContactException(String message, Object request) {
    super(message);
    this.request = request;
  }
  // 省略getter方法
}

控制器抛异常时传入当前请求:

// Add接口中抛异常示例
throw new WebServiceContactException("调用服务失败", addRequest);

异常处理方法就不需要额外接收请求参数,直接从异常对象取值即可。

方案3:拆分多份ControllerAdvice指定作用范围

如果确实要拆分不同的处理方法,可以定义两个不同的@ControllerAdvice类,分别指定生效的控制器范围,每个类中各写一个异常处理方法,避免冲突:

// 仅处理Add相关控制器的异常
@ControllerAdvice(assignableTypes = AddController.class)
public class AddExceptionHandler {
  @ExceptionHandler(WebServiceContactException.class)
  @ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
  @ResponseBody
  public MyResponse dealAddException(WebServiceContactException e, AddRequest request) {
    // 对应处理逻辑
  }
}

// 仅处理Delete相关控制器的异常
@ControllerAdvice(assignableTypes = DeleteController.class)
public class DeleteExceptionHandler {
  @ExceptionHandler(WebServiceContactException.class)
  @ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
  @ResponseBody
  public MyResponse dealDeleteException(WebServiceContactException e, DeleteRequest request) {
    // 对应处理逻辑
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:51:01