Spring Boot WebFlux中数组响应转DTO及合并校验逻辑实现方法
Spring WebFlux 移除WebClient调用中间变量方案
完全可以实现两段逻辑合并,不需要单独定义库存响应数组的中间变量,以下是具体实现方式:
方案1:保留原有同步阻塞逻辑,仅移除中间变量
你可以直接在Mono流内用map算子完成库存状态判断,最后block()直接返回布尔值结果,无需定义中间数组变量:
// Call Inventory Service, and place order if product is in stock boolean allProductsInStock = webClient.get() .uri("http://localhost:8092/api/inventory", uriBuilder -> uriBuilder.queryParam("skuCode", skuCodes).build()) .retrieve() .bodyToMono(InventoryResponse[].class) // 直接在流内完成数组遍历判断 .map(inventoryResponsArray -> Arrays.stream(inventoryResponsArray) .allMatch(InventoryResponse::isInStock)) .block();
注意:这种写法虽然满足移除中间变量的需求,但在Spring WebFlux响应式链路中调用block()会阻塞事件循环线程,彻底丢失响应式编程的非阻塞性能优势,仅适合临时兼容旧逻辑使用。
方案2:符合WebFlux规范的全响应式写法(推荐)
如果你是基于WebFlux开发响应式微服务,建议把整个方法改造成非阻塞的响应式链路,全程不调用block(),从根源上避免不必要的中间变量和阻塞操作:
// 方法返回Mono,全程非阻塞 public Mono<Void> placeOrder(OrderRequest orderRequest) { List<OrderLineItems> orderLineItems = orderRequest.getOrderLineItemsDtoList() .stream() .map(this::mapToDto) .collect(Collectors.toList()); Order order = new Order(); order.setOrderNumber(UUID.randomUUID().toString()); order.setOrderLineItemsList(orderLineItems); List<String> skuCodes = order.getOrderLineItemsList() .stream() .map(orderLineItem -> orderLineItem.getSkuCode()) .collect(Collectors.toList()); // 串联整个库存查询、判断、下单流程 return webClient.get() .uri("http://localhost:8092/api/inventory", uriBuilder -> uriBuilder.queryParam("skuCode", skuCodes).build()) .retrieve() .bodyToMono(InventoryResponse[].class) .map(inventoryArray -> Arrays.stream(inventoryArray) .allMatch(InventoryResponse::isInStock)) .flatMap(allProductsInStock -> allProductsInStock ? // 库存充足则执行响应式保存,注意这里需要使用Reactive类型的OrderRepository orderRepository.save(order).then() : // 库存不足抛出异常 Mono.error(new IllegalArgumentException("Product is not in stock, please try again later")) ); }
注意:该方案要求你的
orderRepository是响应式Repository(即继承ReactiveCrudRepository/ReactiveMongoRepository等响应式数据接口),如果还是传统的阻塞式JPA Repository,会在数据库操作环节产生阻塞,同样不符合WebFlux的使用规范。
内容的提问来源于stack exchange,提问作者Jeff Cook
相关产品推荐
相关产品推荐

