WebFlux条件平面图

时间:2019-08-24 04:22:58

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

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

我有3个简单的实体:

项目,品牌,类别。

项目基本上包含: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中有另一个实体。会有更多的嵌套flatMaps吗?

1 个答案:

答案 0 :(得分:2)

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

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;
}

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