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

如何从Mono<Object>中获取实体对象?Spring WebClient调用block()报错如何解决

你遇到的报错是因为当前代码运行在WebFlux默认的非阻塞EventLoop线程中,Spring默认禁止在这类线程中调用block()这类阻塞API,避免阻塞事件循环导致服务吞吐量下降甚至崩溃。

场景1:项目为Spring WebFlux反应式技术栈

不要强行将Mono转换为同步返回的User对象,顺着反应式流的编程范式调整代码即可,后续发送数据到其他远程服务的逻辑直接通过操作符串联:

  1. 调整findUserById返回值为Mono<User>
public Mono<User> findUserById(String user_id){
    return webClientBuilder.build().get().uri("http://localhost:7854/{userId}", user_id)
            .retrieve()
            .onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus), clientResponse -> Mono.empty())
            .bodyToMono(User.class);
}
  1. 后续调用时用flatMap串联发送到其他服务的逻辑
// 示例逻辑:获取用户后发送到另一个远程服务
public Mono<Void> processUser(String userId) {
    return findUserById(userId)
            .filter(Objects::nonNull) // 过滤404返回的空值,按需调整异常处理逻辑
            .flatMap(user -> otherWebClient.post()
                    .uri("目标远程服务接口地址")
                    .bodyValue(user)
                    .retrieve()
                    .bodyToMono(Void.class)
            );
}

场景2:项目为传统Spring Web Servlet技术栈

如果你只是用WebClient替代RestTemplate做同步HTTP调用,不需要保持反应式特性,可以主动将请求调度到允许阻塞的线程池执行后再调用block():

public User findUserById(String user_id){
    return webClientBuilder.build().get().uri("http://localhost:7854/{userId}", user_id)
            .retrieve()
            .onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus), clientResponse -> Mono.empty())
            .bodyToMono(User.class)
            // 切换到支持阻塞操作的弹性线程池执行
            .subscribeOn(Schedulers.boundedElastic())
            .block();
}

注意事项

  • WebFlux项目不建议使用场景2的方案,会彻底丧失反应式编程的非阻塞优势,还可能引发线程资源耗尽问题。
  • 原代码中直接字符串拼接URI存在注入风险,建议使用WebClient自带的路径参数占位符写法。
  • 404返回Mono.empty()的逻辑需要配套后续空值判断,避免出现空指针异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:54:03