在哪里使用Mono/Flux?
Where to use Mono/Flux?
我有点被迫转向使用 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);
换句话说,我是不是被迫在任何地方都使用这个管道来保持响应性,或者以命令的方式执行某些步骤,比如打开对象,处理它,然后把它包装回去?
我知道我的问题似乎很愚蠢,但我根本没有大局观,阅读有关它的书籍并没有真正帮助,请对我温柔一点。 :)
当您需要顺序、异步和惰性执行时使用流水线。在所有其他情况下(当您使用非阻塞代码时)您可以自由选择任何方法,通常最好使用最简单的方法。
顺序非阻塞代码可以组织成函数,您可以使用 map/filter/doOnNext/... 组件将这些代码与反应管道集成。
例如,考虑以下 Order
价格计算代码。
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)
}
}
我有点被迫转向使用 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);
换句话说,我是不是被迫在任何地方都使用这个管道来保持响应性,或者以命令的方式执行某些步骤,比如打开对象,处理它,然后把它包装回去?
我知道我的问题似乎很愚蠢,但我根本没有大局观,阅读有关它的书籍并没有真正帮助,请对我温柔一点。 :)
当您需要顺序、异步和惰性执行时使用流水线。在所有其他情况下(当您使用非阻塞代码时)您可以自由选择任何方法,通常最好使用最简单的方法。
顺序非阻塞代码可以组织成函数,您可以使用 map/filter/doOnNext/... 组件将这些代码与反应管道集成。
例如,考虑以下 Order
价格计算代码。
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)
}
}