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

Spring WebFlux中doOnSuccess/doOnError/onErrorContinue未执行问题

问题分析
  1. 冷流未订阅导致操作符失效:控制器里手动subscribe的流中,doOnNext内的useCase.doSomething(xxx)只是创建了一个Mono冷流,但没有被订阅(响应式冷流只有被订阅才会执行逻辑),所以里面的onErrorContinue和doOnSuccess完全不会触发。
  2. 独立流逻辑重复:你同时启动了两个毫无关联的流——一个手动订阅,另一个返回给Spring处理,既造成逻辑重复,也让两个流的执行状态完全割裂。
  3. 语法错误:doSomething里的Mono.when缺少闭合括号,正确写法应为Mono.when(firstAction(xxx), secondAction(xxx)),这也是影响执行的潜在问题。
解决方案

修改控制器逻辑,将整个流程合并为单一流,让Spring WebFlux负责订阅,同时精准控制错误传播范围:

private final Map<String, MyUseCase> myUseCase;

// 控制器核心方法
public Mono<Void> yourControllerMethod(String param, InputValues xxx) {
    return retrieveServiceByParam(param)
        .flatMap(useCase -> 
            // 执行业务逻辑,拦截内部错误仅记录日志
            useCase.doSomething(xxx)
                .onErrorContinue((throwable, obj) -> 
                    log.error("doSomething执行失败: {}", throwable.getMessage(), throwable)
                )
        )
        .subscribeOn(Schedulers.boundedElastic())
        .then();
}

private Mono<MyUseCase> retrieveServiceByParam(final String param) {
    return MyEnum.find(param)
        .doOnError(throwable -> {
            throw new NotFoundException("指定服务不存在");
        })
        .map(myUseCase::get);
}

同时修正doSomething的语法错误,可保留内部的成功日志(如果不需要双重错误拦截,可移除内部的onErrorContinue):

@Override
public Mono<Void> doSomething(final InputValues inputValues) {
    return Mono.when(
            firstAction(xxx),
            secondAction(xxx)
        )
        .doOnSuccess(a -> log.info("doSomething执行成功"));
}
关键说明
  • 流串联执行:用flatMap替代doOnNext,将doSomething的流合并到主流程中,确保Spring订阅主流程时,业务逻辑会被触发执行。
  • 错误范围隔离:retrieveServiceByParam抛出的NotFoundException会向上传播,最终由Spring返回给用户;doSomething内部的错误被onErrorContinue拦截,仅记录日志,不会影响API响应结果。
  • 避免重复操作:仅调用一次retrieveServiceByParam,避免重复查找服务和创建冗余流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:10:29