Spring Boot自定义异常处理器未按预期抛出异常问题排查
问题现状
期望支付方式无效时的错误响应:
{ "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内部服务器错误。
核心原因分析
Controller层全局拦截所有异常
在BookingController的completePayment方法中,使用catch (Exception e)捕获了所有类型的异常,包括自定义的InvalidPaymentModeException。异常抛出后直接被该catch块处理并返回500错误,根本无法传递到@ControllerAdvice修饰的自定义异常处理器中。控制台日志佐证逻辑
从控制台日志可见,代码执行完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

