如何在WebFlux Controller中实现订阅,避免block()阻塞报错
问题核心原因
WebFlux 基于 Reactor 响应式框架设计,全程要求非阻塞运行,block() 属于阻塞操作,会占用反应器线程触发报错。你尝试的share()只是实现多播数据源的操作,本质还是走阻塞调用,自然会出现无限挂起的问题。
正确实现方案
你需要用响应式流的链式操作将两次请求串联,全程不使用阻塞方法,同时要修改控制器的返回值为 Publisher 类型(Mono/Flux),让框架可以正确调度异步流程。flatMap是Reactor中处理异步嵌套调用的标准操作符,它会在上游请求完成拿到结果后,自动触发下游的第二次请求,全程由框架调度非阻塞线程执行,不会出现阻塞报错问题。
正确代码示例如下:
@PostMapping public Mono<PostResult> abbina(@RequestBody DocumentsUploadRequest documentsUploadRequest) { // 第一次调用GET接口获取结果 return WebClient .create(url) .get() // 省略其余请求配置 .retrieve() .bodyToMono(GetResult.class) // 拿到第一次请求结果后,触发第二次POST请求 .flatMap(getResult -> WebClient.post() .uri(uriBuilder -> uriBuilder .path(/* 基础路径配置 */) .path("/{partita}") .build(getResult.getValue()) ) // 省略其余POST请求配置 .retrieve() .bodyToMono(PostResult.class) ); }
注意事项
- 如果不需要给接口调用方返回
PostResult结果,可以在代码最后追加.then(),方法返回值改为Mono<Void>即可。 - 业务逻辑中不要调用任何
block()、blockFirst()、blockLast()这类阻塞API,所有依赖上游结果的操作都通过flatMap、map这类非阻塞操作符实现。
内容的提问来源于stack exchange,提问作者Dmitrij Colautti
相关产品推荐
相关产品推荐

