Spring WebFlux中doOnSuccess/doOnError/onErrorContinue未执行问题
问题分析
- 冷流未订阅导致操作符失效:控制器里手动
subscribe的流中,doOnNext内的useCase.doSomething(xxx)只是创建了一个Mono冷流,但没有被订阅(响应式冷流只有被订阅才会执行逻辑),所以里面的onErrorContinue和doOnSuccess完全不会触发。 - 独立流逻辑重复:你同时启动了两个毫无关联的流——一个手动订阅,另一个返回给Spring处理,既造成逻辑重复,也让两个流的执行状态完全割裂。
- 语法错误:
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
相关产品推荐
相关产品推荐

