WebFlux中如何根据Flux是否包含元素返回不同响应?
问题根因
Reactor 中 Flux 属于冷流,默认每次订阅都会触发完整的数据流生成逻辑。你的代码里 rooms 流的源头是 serverRequest.bodyToMono(PageBO.class),而 HTTP 请求的 body 只能被读取一次:
- 第一次订阅发生在
hasElements()方法调用时,已经完整读取了请求 body、执行了查询,消费了所有数据 - 第二次订阅发生在
ServerResponse.ok().body(rooms,RoomBO.class)时,此时请求 body 已经为空,所以拿到的是空流,最终返回空数组
解决方法
方案1:给 Flux 添加缓存
调用 cache() 操作符让第一次订阅的结果被缓存,后续订阅直接复用缓存数据,不需要重新读取请求 body:
Flux<RoomBO> rooms=serverRequest.bodyToMono(PageBO.class) .flatMapMany(roomRepository::getRooms) .cache(); // 新增缓存操作符 return rooms.hasElements().flatMap(aBool -> aBool?ServerResponse.ok().body(rooms,RoomBO.class):ServerResponse.badRequest().build());
方案2:先收集结果再判断(更推荐,避免两次订阅逻辑)
直接把结果收集为 List,一次订阅完成判断和返回逻辑,没有额外的缓存开销:
return serverRequest.bodyToMono(PageBO.class) .flatMapMany(roomRepository::getRooms) .collectList() .flatMap(roomList -> { if(roomList.isEmpty()){ return ServerResponse.badRequest().build(); } return ServerResponse.ok().bodyValue(roomList); });
方案3:用 switchIfEmpty 简化逻辑
如果业务允许直接在流为空的时候返回异常,可以用 switchIfEmpty 直接抛出自定义异常,再配合全局异常处理器返回400,代码更简洁:
return ServerResponse.ok().body( serverRequest.bodyToMono(PageBO.class) .flatMapMany(roomRepository::getRooms) .switchIfEmpty(Mono.error(new IllegalArgumentException("房间列表为空"))), RoomBO.class );
内容的提问来源于stack exchange,提问作者softgreet
相关产品推荐
相关产品推荐

