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

CompletableFuture supplyAsync块内抛出异常无法被自定义异常处理器捕获如何解决

问题根源

Spring MVC 本身支持 Controller 直接返回 CompletableFuture 类型的返回值,框架会自动异步等待结果完成后再处理响应。你遇到的异常无法被全局处理器捕获的核心原因是:你在各层的 supplyAsync 块内手动捕获了异常,没有将异常传递到返回的 CompletableFuture 中,框架感知不到异常发生,自然不会触发 @ExceptionHandler 逻辑。

正确修改方案

1. Controller 层调整

不要在 supplyAsync 内吞掉异常,异常会自动被封装到返回的 CompletableFuture 中,方法上声明的 throws 也没有意义(异步异常不会走同步调用栈抛出):

@PostMapping(path="/offers/offer")
public CompletableFuture<Oferta> infoPropiedad(@Valid @RequestBody OfertaRequest inDTO) {
    System.out.println("THREAD: "+Thread.currentThread().getName());
    return CompletableFuture.supplyAsync(()->{
        // 不需要手动捕获异常,抛出的异常会自动存入CompletableFuture
        return ofertasService.ofertasService(inDTO);
    });
}

2. Service 层调整

Supplier 接口不允许抛出受检异常,所以捕获到异常后需要包装为 CompletionException 抛出,异常会自动携带到对应的 CompletableFuture 中:

CompletableFuture<OfertaCrm> completableFutureCRM = 
                CompletableFuture.supplyAsync(()->  {
                    try {
                        return clientOferta.llamadaWebServiceOfertas(inDTOCrm);
                    } catch (Exception e1) {
                        // 包装后抛出,不要吞异常
                        throw new CompletionException(e1);
                    }
                });

3. ClientWs 层无需调整

原有抛出 SOAPException、IOException 等受检异常的逻辑保留即可,不需要额外处理。

额外说明

Spring 4.3 及以上版本的全局异常处理器会自动解包 CompletableFuture 抛出的 CompletionException,匹配内部的根异常类型,你现有的 @ExceptionHandler 配置不需要修改,就能正常捕获 SOAPException、IOException 等你声明的异常类型。

如果使用自定义线程池执行异步任务,确保线程池没有配置自定义的 UncaughtExceptionHandler 吞掉异常,默认线程池配置不会有这个问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:57:02