Spring响应式:如何在Flux.concat中复用单次获取的Mono<Sleep>?
解决方案
核心思路是先一次性获取Sleep对象,再基于该对象执行所有检查,这样就能避免重复调用外部API,同时绕开lambda变量的final限制。
步骤1:重构检查方法
把所有检查方法的入参从Student改成Sleep,因为我们已经提前拿到了Sleep实例,不需要再通过Student去调用API:
// 重构后的isHealthy,直接接收Sleep对象 public Mono<Boolean> isHealthy(Sleep sleep) { return Mono.just(sleep.isValid()); } // 同理重构isWealthy和isWise public Mono<Boolean> isWealthy(Sleep sleep) { // 这里写你的检查逻辑,直接用传入的sleep对象 return Mono.just(sleep.isWealthy()); } public Mono<Boolean> isWise(Sleep sleep) { // 这里写你的检查逻辑,直接用传入的sleep对象 return Mono.just(sleep.isWise()); }
步骤2:重写checkSleep方法
先调用一次extService.getSleep(std)获取Sleep的Mono,再在flatMap里基于这个Sleep实例执行所有检查,最后保留你原来的判断逻辑:
public Mono<Boolean> checkSleep(Student std) { // 只调用一次外部API获取Sleep return extService.getSleep(std) .flatMap(sleep -> // 基于同一个sleep对象执行三个检查 Flux.concat(isHealthy(sleep), isWealthy(sleep), isWise(sleep)) .filter(result -> !result) .next() // 只要有一个检查不通过,返回false .flatMap(result -> Mono.just(false)) // 所有检查都通过,返回true .switchIfEmpty(Mono.just(true)) ); }
为什么这个方案可行?
extService.getSleep(std)只会被调用一次,后续所有检查都复用同一个Sleep实例;- 在
flatMap内部可以直接使用sleep变量,因为它是该lambda作用域内的局部变量,天然满足effectively final的要求; - 完全保留了你原来的业务逻辑:只要有一个检查返回false,整个方法就返回false;全部通过则返回true。
内容的提问来源于stack exchange,提问作者Mohammed Idris
相关产品推荐
相关产品推荐

