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

Java响应式编程中抛出异常无法在控制器捕获的问题排查

问题分析与解决方案

你的代码存在几个核心问题,导致响应式流中的异常无法被捕获:


1. 同步try-catch无法捕获响应式流内的异常

响应式编程中,Mono/Flux操作符(比如map)内抛出的异常是作为流的错误信号存在的,并非同步抛出的异常。普通的try-catch块只能捕获当前线程同步执行时的异常,根本无法触及流内部异步执行时抛出的异常。

2. 响应式流未被触发执行

在MyClass.getData()方法中,你只是创建了Mono<String>对象,但没有触发流的执行:

  • 如果是WebFlux控制器,需要直接返回Mono对象,由框架自动处理订阅;
  • 如果是普通方法,需要调用subscribe()(异步执行)或block()(同步阻塞,Web环境不推荐)来启动流。
    流未执行的情况下,自然不会触发任何异常。

3. 服务层的try-catch完全无效

MyService.getResponseData()中的try-catch包裹的是Mono的创建代码,而map操作符内的异常是在流订阅执行阶段才会抛出的,这个try-catch根本无法捕获到这些异常。


修正后的代码示例

控制器层(正确处理响应式异常)

如果是WebFlux控制器,直接返回Mono并通过响应式错误操作符处理异常:

public class MyController {
    public Mono<String> getData() {
        return myService.getResponseData(1)
                // 处理CustomException类型的异常
                .onErrorResume(CustomException.class, e -> {
                    // 这里添加CustomException的专属处理逻辑
                    return Mono.just("Custom异常处理后的返回结果");
                })
                // 处理其他所有类型的异常
                .onErrorResume(Exception.class, e -> {
                    // 这里添加通用异常处理逻辑
                    return Mono.just("通用异常处理后的返回结果");
                });
    }
}

服务层(移除无效try-catch,让异常流入错误信号)

public class MyService {
    public Mono<String> getResponseData(int number) {
        return myDbDTO1.table1(number)
                .map(result -> {
                    if (validatingSomeCondition) {
                        throw new CustomException("Invalid data!");
                    }
                    return result;
                })
                .zipWhen(result -> myDbDTO2.table2(number).collectList())
                .map(m1 -> mapResults(m1.getT1(), m1.getT2()));
    }
}

mapResults方法(保持原有逻辑即可)

该方法内同步抛出的异常会被map操作符捕获,自动转为流的错误信号向下传递:

public Result mapResults(Result1 res1, Result2 res2) {
    try {
        // 合并两个对象的逻辑
        return new Result(res1, res2);
    } catch (Exception e) {
        throw new CustomException("Invalid data!");
    }
}

关键注意事项

  • 响应式异常处理必须使用Reactor提供的错误操作符:onErrorResume(替换错误信号为新的流)、onErrorReturn(返回默认值)、onErrorMap(转换异常类型)等。
  • 永远不要用同步try-catch包裹响应式流的操作符,这是响应式编程的常见误区。
  • 确保流被正确订阅:WebFlux环境下返回Mono/Flux即可,非Web环境需调用subscribe()或block()启动流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:10:18