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

Spring Boot自定义异常处理器未按预期抛出异常问题排查

问题排查:InvalidPaymentModeException未被自定义异常处理器捕获的原因及解决方法

问题现状

期望支付方式无效时的错误响应:

{
   "message": " Invalid Booking Id ",
  "statusCode": 400
}

实际返回的错误响应:

{
    "type": "about:blank",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "Failed to write request",
    "instance": "/hotel/booking/1/transaction"
}

当支付方式不为"UPI"或"CARD"时,代码会抛出InvalidPaymentModeException,但该异常未被自定义异常处理器捕获,反而触发通用逻辑返回500内部服务器错误。

核心原因分析

  1. Controller层全局拦截所有异常
    在BookingController的completePayment方法中,使用catch (Exception e)捕获了所有类型的异常,包括自定义的InvalidPaymentModeException。异常抛出后直接被该catch块处理并返回500错误,根本无法传递到@ControllerAdvice修饰的自定义异常处理器中。

  2. 控制台日志佐证逻辑
    从控制台日志可见,代码执行完isValidPaymentMode后直接退出completePayment方法,无异常抛出的日志输出,说明异常确实被内部catch块拦截处理。

解决方法

方法一:缩小Controller层异常捕获范围

修改completePayment方法的catch块,仅捕获特定业务场景的异常(比如RestTemplate调用相关异常),让InvalidPaymentModeException能够向上传递到自定义处理器:

public ResponseEntity<?> completePayment(@PathVariable(name = "id") int id, @RequestBody TransactionRequestDto transactionRequestDto) {
    try{
        // 原有业务逻辑代码...
    } catch (RestClientException e) { // 仅捕获支付服务调用相关异常
        com.example.bookingservice.dto.ErrorResponse errorResponse = new com.example.bookingservice.dto.ErrorResponse("Payment Service Call Failed", HttpStatus.INTERNAL_SERVER_ERROR.value());
        return new ResponseEntity(errorResponse,HttpStatus.INTERNAL_SERVER_ERROR);
    }
    // 其他异常(含InvalidPaymentModeException)自动交由自定义处理器处理
}

方法二:在catch块中重新抛出自定义异常

若必须保留全局catch块,可在其中判断异常类型,对InvalidPaymentModeException重新抛出,交给自定义处理器接管:

catch (Exception e){
    if(e instanceof InvalidPaymentModeException){
        throw (InvalidPaymentModeException) e; // 重新抛出自定义异常
    }
    com.example.bookingservice.dto.ErrorResponse errorResponse = new com.example.bookingservice.dto.ErrorResponse("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.value());
    return new ResponseEntity(errorResponse,HttpStatus.INTERNAL_SERVER_ERROR);
}

方法三:移除Controller层全局try-catch(推荐)

Spring Boot的全局异常处理器本身用于统一处理异常,Controller层无需手动捕获所有异常,直接让异常向上抛出,自定义异常处理器即可正常拦截并返回指定格式的400错误响应。

补充验证点

确认InvalidPaymentModeException是RuntimeException的子类(代码已满足),@ExceptionHandler默认处理未被捕获的RuntimeException及其子类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:33:31