如何使用spring webflux在功能性反应java中编写具有多个if else的复杂代码
Posted
技术标签:
【中文标题】如何使用spring webflux在功能性反应java中编写具有多个if else的复杂代码【英文标题】:How to write complex code with multiple if else in functional reactive java using spring webflux 【发布时间】:2019-09-22 01:58:38 【问题描述】:我是 RXjava 函数式编程的新手。我正在编写具有多个条件的 post 端点:
-
当 post 端点被产品击中时
如果登录用户的购物车在数据库中不存在,则创建一个新购物车
如果购物车已经存在于沙发底座中,则提取该记录并检查产品 JSON 是否给定产品 ID 已存在于产品 JSON 中。
如果它在产品 JSON 中不可用,则必须创建新产品
应使用新创建的 productId 更新购物车
如果它存在于产品 JSON 中,则获取产品记录并验证数量。
如果数量相同,则什么也不做
否则,更新记录。
我面临着在函数式编程中编写这些 if else 条件的挑战。尝试使用switchifEmpty
并无法在其中编写代码。
这是一个示例代码。
public Mono<Product> createProduct(final Tuple2<String, productdto> tuple2)
final Product productdto = tuple2.getT2();
return Mono.just(tuple2.getT1())
.map(cartRepository::findById)
.defaultIfEmpty(cartRepository.save(
cart.builder()
.id(tuple2.getT1())
.build()))
.flatMap(cartres -> cartres)
.flatMap(cartres ->
final Product product = Product.builder()
.id(1234)
.productId(productDTO.getProductId())
.productName(productDTO.getProductName())
.build();
return productRepository.save(product)
.map(saveCart -> cart.builder()
.id(cartres.getId()).build())
.flatMap(cartRepository::save);
);
).then(Mono.just(productDto));
【问题讨论】:
【参考方案1】:我知道有一个复杂的 if-else-logic,您必须使用带有 .map()
、.flatMap()
或 defaultIfEmpty()
的 Spring WebFlux 调用的反应链来实现。
这些反应式运算符不能总是替换复杂的 if-else-logic。
必须在 .map()
或 .flatMap()
处理程序中执行 if-else-decisions。
在您的情况下,您可以为每个步骤 1..8 实现 java.util.Function<>
或简单方法
下面是第一个示例,该功能通过从 repo 加载或创建新的来为您提供购物车。
此外,它还展示了如何使用zipWith()
运算符向反应链添加更多数据。
这里检查数据库中产品的存在,并将结果作为布尔值传递给下游。
基于此布尔值,您可以使用 if-else-statement 来返回现有产品或创建新产品。
public Mono<Product> createProduct(final Tuple2<String, Product> tuple2)
final Product productDTO = tuple2.getT2();
return Mono.just(tuple2.getT1())
// .map(cartRepository::findById)
// .defaultIfEmpty(cartRepository.save(
// cart.builder()
// .id(tuple2.getT1())
// .build()))
.flatMap(provideCart(tuple2)) // see implemented method further below
.flatMap(cartres -> cartres)
.map(cartres -> cartres)
.zipWith(productRepository.existsById(productDTO.getId()))
.flatMap(maybeCreateProduct(productDTO)); // see implemented method further below
private Function<String, Mono<Cart>> provideCart(final Tuple2<String, Product> tuple2)
return id -> cartRepository.findById(id)
.switchIfEmpty(cartRepository.save(
Cart.builder()
.id(tuple2.getT1())
.build()));
private Function<Tuple2<Cart, Boolean>, Mono<Product>> maybeCreateProduct(Product productDTO)
return cartresAndProductExists ->
Cart cart = cartresAndProductExists.getT1();
Boolean productExists = cartresAndProductExists.getT2();
if (productExists)
return productRepository.findById(productDTO.getProductId())
else
return productRepository.save(Product.builder()
.id("1234")
.productId(productDTO.getProductId())
.productName(productDTO.getProductName())
.build());
;
必须小心保持代码可读性并避免无休止的反应步骤链。
将复杂的步骤提取到单独的方法中,甚至可能首先重新考虑流程以获得更简单和精简的解决方案
【讨论】:
以上是关于如何使用spring webflux在功能性反应java中编写具有多个if else的复杂代码的主要内容,如果未能解决你的问题,请参考以下文章
Spring WebFlux 教程:如何构建反应式 Web 应用程序
反应式编程:Spring WebFlux:如何构建微服务调用链?
如何使 WebFilter 在非 WebFlux/非反应式 Spring Boot 应用程序中工作?