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

Thymeleaf场景下Controller无法捕获OTPException问题求助

Controller无法捕获OTPException异常的问题分析与解决

问题场景

在Controller方法中通过try-catch尝试捕获OTPException,但当service抛出该异常时,catch块无法命中;即使捕获Exception后判断e instanceof OTPException也不成立,同时存在标注了@Order(Ordered.HIGHEST_PRECEDENCE)的全局异常处理器处理OTPException。

核心原因

你代码中调用了service.generate(...).get(),这里的get()属于Future接口的同步阻塞方法,它会将任务执行过程中抛出的原始异常**包装为ExecutionException**抛出。也就是说,Controller方法实际接收到的异常是ExecutionException,而非直接的OTPException——这就是catch(OTPException)无法触发、instanceof判断不成立的根本原因。

解决方案

方案1:捕获包装异常,提取原始异常

修改Controller的try-catch逻辑,先捕获ExecutionException,再从其内部取出原始异常进行判断:

@GetMapping
public String popup() {
    try {
         service.generate(new ExistOTPValidQuery().requestNumber("test"), Boolean.class).get();
    } catch (ExecutionException e) {
        Throwable cause = e.getCause();
        if (cause instanceof OTPException) {
              return "user";
        }
        // 处理其他类型异常
        throw new RuntimeException(cause);
    } catch (InterruptedException e) {
        // 恢复线程中断状态
        Thread.currentThread().interrupt();
        return "error";
    }
    return "error";
}

注意:Future.get()还会抛出InterruptedException,需额外捕获并处理,避免线程中断状态丢失。

方案2:改用异步回调(推荐)

如果service是异步方法,建议用CompletableFuture替代普通Future,通过回调处理异常,避免同步阻塞和异常包装:

@GetMapping
public String popup() {
    service.generate(new ExistOTPValidQuery().requestNumber("test"), Boolean.class)
        .whenComplete((result, ex) -> {
            if (ex != null) {
                if (ex.getCause() instanceof OTPException) {
                    // 处理OTP异常逻辑
                } else {
                    // 处理其他异常
                }
            } else {
                // 处理正常结果
            }
        });
    return "user"; // 根据业务调整返回值
}

方案3:扩展全局异常处理器(可选)

如果希望全局异常处理器能处理包装后的异常,可新增对ExecutionException的处理逻辑,提取内部的OTPException:

@ExceptionHandler(ExecutionException.class)
public ResponseEntity<Object> executionException(ExecutionException ex) {
    Throwable cause = ex.getCause();
    if (cause instanceof OTPException) {
        return otpException((OTPException) cause);
    }
    // 处理其他包装异常
    return buildResponseEntity(new ApiError(CustomHttpStatus.ERROR, new Date(), ex.getMessage()),
        HttpStatus.INTERNAL_SERVER_ERROR);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 05:27:32