在哪些情况下使用Mono/Flux?

3

我被迫转换到响应式编程(并且时间紧迫),使用WebFlux,但我很难理解它。可能是因为缺乏示例或因为我从未进行过函数式编程。

无论如何,我的问题是在哪里使用Mono/Flux,在哪里可以使用普通对象?例如,我的控制器正在等待@Valid User对象,那应该是@Valid Mono还是类似于Mono<@Valid User>的东西?如果说只是一个User对象,我将其传递给我的服务层,并且我想在保存到响应式MongoDb之前对密码进行编码,那么我应该写:

User.setPassword(...);
return reactiveMongoDbRepository.save(user); //returns Mono<User> which is returned by the Controller to the View

或者应该是这样的:
return Mono.just(user).map.flatmap(setPasswordSomewhereInThisHardToFollowChain).then.whatever.doOnSuccess(reactiveMongoDbRepository::save);

换句话说,我是否被迫在任何地方都使用这个“管道”来保持反应性,或者像解开对象、操作它,然后再包装回去这样的步骤是可以的?
我知道我的问题似乎很傻,但我完全没有整体概念,阅读相关书籍也没有真正帮助我,所以请对我温柔点。 :)

1
第一种方法没有问题。 当需要顺序、异步和惰性执行时,请使用管道技术。 在所有其他情况下(当您使用非阻塞代码时),您可以自由选择任何方法,通常最好使用最简单的方法。 - Ilya Zinkovich
@IlyaZinkovich 所以基本上我可以在除了控制器和存储库层之外的任何地方使用用户对象? - Peter
1
将您的命令式代码封装在函数中,然后将其一起提供给Mono/Flux的某些映射/过滤/消费函数。 - Ilya Zinkovich
@IlyaZinkovich非常感谢您,先生! :) - Peter
1
感谢 @IlyaZinkovich! - Brian Clozel
显示剩余4条评论
1个回答

3
使用管道技术实现顺序、异步和延迟执行。在其他情况下(使用非阻塞代码),您可以自由选择任何方法,通常最好使用最简单的方法。
顺序非阻塞代码可以组织为函数,并使用 map/filter/doOnNext/... 组件与反应式管道集成。
例如,考虑以下订单价格计算代码。
class PriceCalculator {

  private final Map<ProductCode, Price> prices;

  PriceCalculator(Map<ProductCode, Price> prices) {
    this.prices = prices;
  }

  PricedOrder calculatePrice(Order order) { // doesn't deal with Mono/Flux stuff
    Double price = order.orderLines.stream()
      .map(orderLine -> prices.get(orderLine.productCode))
      .map(Price::doubleValue)
      .sum();
    return new PricedOrder(order, price);
  }
}

class PricingController {

  public Mono<PricedOrder> getPricedOrder(ServerRequest request) {
    OrderId orderId = new OrderId(request.pathVariable("orderId"));
    Mono<Order> order = orderRepository.get(orderId);
    return order.map(priceCalculator::calculatePrice)
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接