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

Spring Webflux中WebClient调用后FlatMap方法未执行问题求助

问题原因与解决方案

核心故障点1:Reactor空值异常导致流中断

Reactive Streams规范明确禁止Publisher发射null值,你的userInfoById方法中存在如下风险逻辑:

responseMono = response.bodyToMono(UserInfoResponse.class)
    .flatMap(uir -> Mono.just(uir.getData()));

如果uir.getData()返回null,Mono.just(null)会直接抛出NullPointerException,让getUserInfo(userId)返回的Mono进入错误状态,后续的.flatMap(ui -> crmDeleteAttribute(ui, attribute))逻辑会直接跳过,没有错误日志的情况下你只会看到用户信息接口调用完成,后续流程无响应。

核心故障点2:exchange()方法资源泄漏阻塞后续请求

Spring WebFlux 5.3+已经将WebClient.exchange()标记为废弃,该方法需要开发者手动管理响应资源的释放,一旦资源释放逻辑有遗漏,会快速占满HTTP连接池,后续的打标签DELETE请求根本拿不到连接,自然不会执行。

次要排查点:空列表导致流无发射元素

请确认haveNoGroupsList(users, friends)方法的返回值:如果该方法返回空集合,Flux.fromIterable(noGroupUsers)会直接创建空流,不会触发任何后续的deleteAttribute调用。


修复代码示例

1. 修复userInfoById方法

public Mono<UserInfo> userInfoById(final String userId) {
    return webClient.get()
        .uri(uriBuilder -> uriBuilder.path(constants.getByIdPath() + "/{id}")
            .build(userId))
        .header("auth", tokenService.token())
        // 替换exchange为exchangeToMono,自动管理响应资源
        .exchangeToMono(response -> {
            if (response.statusCode().equals(HttpStatus.UNAUTHORIZED)) {
                return Mono.error(new UnauthorizedException());
            } else if (response.statusCode().equals(HttpStatus.OK)) {
                return response.bodyToMono(UserInfoResponse.class)
                    .map(UserInfoResponse::getData)
                    // 处理getData为null的情况,避免空指针
                    .switchIfEmpty(Mono.error(new RuntimeException("用户信息为空")));
            } else {
                return Mono.error(new UnhandledException());
            }
        })
        // 增加错误日志,方便排查问题
        .doOnError(e -> log.error("获取用户信息失败, userId:{}", userId, e));
}

2. 给deleteAttribute增加错误日志

public Mono<Boolean> deleteAttribute(final String userId, final String attribute) {
    return getUserInfo(userId)
        .flatMap(ui -> crmDeleteAttribute(ui, attribute))
        .doOnError(e -> log.error("删除用户标签失败, userId:{}, attribute:{}", userId, attribute, e));
}

3. 增加空列表日志确认

在checkUserHaveGroup方法中增加日志确认未入群用户数量:

return this.reactiveMongoTemplate.aggregate(a, FriendInGroup.class)
    .map(friendInGroup -> friendInGroup.id)
    .collectList()
    .map(users -> haveNoGroupsList(users, friends))
    // 打印未入群用户数量,确认流是否有后续执行逻辑
    .doOnNext(noGroupUsers -> log.info("未入群用户数量:{}", noGroupUsers.size()))
    .flatMapMany(noGroupUsers -> Flux.fromIterable(noGroupUsers)
        .flatMap(pn -> crmService.deleteAttribute(pn, "joinedAGroup"))
    );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 03:57:02