【问题标题】:WebFlux Conditional FlatMapWebFlux 条件平面图
【发布时间】:2019-08-24 04:22:58
【问题描述】:

我对 webflux 比较陌生,我想找到解决方案来避免在有条件时嵌套 flatMap:

我有 3 个简单的实体:

项目、品牌、类别。

Item 基本包含:brandId 和 categoryId

public Mono<Item> patch(String itemId, PatchSpecs specs) {
return itemRepository.findById(itemId)
        .switchIfEmpty(Mono.error(..)))
        .flatMap(item -> {
            final String brandId = specs.getBrandId();
            if (brandId != null) {
                return brandService.getById(brandId)
                        .switchIfEmpty(Mono.error(..)))
                        .flatMap(brand -> {
                            final String categoryId = specs.getCategoryId();
                            if (categoryId != null) {
                               return categoryService.getById(categoryId)... -> return updateAndSave(..)
                            }
                            return updateAndSave(specs, item, brand, null);
                        });
            }
            else {
                final String categoryId = specs.getCategoryId();
                if (categoryId != null) {
                     return categoryService.getById(categoryId)... -> return updateAndSave(..)
                }
                return updateAndSave(specs, item, null, null);
            }

        });
}

如何防止这种分支条件 flatMaps 混乱?我无法想象我是否在 Item 中有另一个实体。会有更多嵌套的 flatMap 吗?

【问题讨论】:

  • 产品变量从何而来?
  • 抱歉打错了我的意思是商品不是产品

标签: java reactive-programming spring-webflux project-reactor


【解决方案1】:

如果我理解您的代码,类别和品牌是商品的可选属性。在这种情况下,我建议如下:

public Mono<Item> patch(String itemId, PatchSpecs specs)
{
    return itemRepository.findById(itemId)
                         .switchIfEmpty(Mono.error(new RuntimeException("Can not find item.")))
                         .flatMap(item -> updateAndSave(specs, item));
}

private Mono<? extends Item> updateAndSave(PatchSpecs specs, Item item)
{
    Mono<Optional<Brand>> brand = getBrand(specs.getBrandId());
    Mono<Optional<Category>> category = getCategory(specs.getCategoryId());

    return Mono.zip(Mono.just(item), brand, category)
               .flatMap(tuple -> updateAndSave(specs, tuple));
}

private Mono<Optional<Brand>> getBrand(String inputBrandId)
{
    return Mono.justOrEmpty(inputBrandId)
               .flatMap(brandId -> brandService.getById(brandId)
                                               .switchIfEmpty(Mono.error(new RuntimeException("Can not find brand."))))
               .map(Optional::of)
               .defaultIfEmpty(Optional.empty());
}

private Mono<Optional<Category>> getCategory(String inputCategoryId)
{
    return Mono.justOrEmpty(inputCategoryId)
               .flatMap(brandId -> categoryService.getById(brandId)
                                                  .switchIfEmpty(Mono.error(new RuntimeException("Can not find brand."))))
               .map(Optional::of)
               .defaultIfEmpty(Optional.empty());
}

private Mono<Item> updateAndSave(PatchSpecs specs, Tuple3<Item, Optional<Brand>, Optional<Category>> tuple)
{
    Item item = tuple.getT1();
    Brand brand = tuple.getT2().orElse(null);
    Category category = tuple.getT3().orElse(null);

    // TODO do update and save here
    return null;
}

这种方式将更具可扩展性,并且不需要重复和嵌套条件。请验证它是否按预期工作。

【讨论】:

  • 看起来好多了。我想确认 tuple.getT1() 是否是非阻塞操作?例如,如果我们使用 categoryIds 列表而不是 categoryId,它会起作用吗? tuple.getT3() 是否适用于 Flux> ?
  • 是的,元组包含了到达后的结果,所以它是非阻塞的。
  • 如果您有 Flux 可能是另一个问题。在这种情况下,您可以使用 collectList 运算符,但我应该看到代码来确定。
  • 你能用单声道压缩助焊剂吗?它只会得到通量的第一个元素吗?
  • 因为 List 已经有一个空状态。如果你使用 collectList 运算符(我不确定你是否这样做),那么一个空的通量将导致一个带有空列表的单声道。
猜你喜欢
  • 2021-05-08
  • 1970-01-01
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2021-09-28
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多