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
相关产品推荐
相关产品推荐

