【问题标题】:Recursively calling Mono functions with Reactive webclient使用 Reactive webclient 递归调用 Mono 函数
【发布时间】:2020-12-28 23:15:57
【问题描述】:

需要从 Mono 递归调用 Mono 以获得完整的 Item。 我有一个 Pojo Item ,在这里我将传递根 id 并尝试从另一个服务中获取该项目。我正在使用 弹出webflux。所以我使用 webclient 来调用服务并返回 Mono

其他服务将提供该项目及其直系子项。 所以我的要求是当我传递 ROOT id 时,我将获得 Root 项及其直接子项,Root 将具有 LM 类型的项作为子项。

获得 Root 项目后,我需要收集所有 LM id 并再次为每个 LM id 调用 ItemService 并将它们设置回 root 项目。

这是我的代码。发生的事情首先是我的 RootItem 正在返回,然后获取 LM 项目的调用正在订阅。 我想首先获取所有 LM 项目并将它们设置为 root 并用新的 LM 项目响应 RootItem。


String itemId,
String ItemName,
List<Item> items
ItemType itemType

}

Enum ItemType {

LM,ROOT,LEAF

}


getItem(itemId) {

// Returns Mono<Item> by calling anthoer service which gives me Item . Here I am using Reactive webclient to call other service.

}

getFullItem(itemId) {

    return getItem(itemId)
        .flatMap(mainItem -> {
            Predicate<Item> LM_Prdicate = p -> p.getItemType().equals(LM);
            // get the LM's from main item. at this point the LM items will not have child
            //we need to get the LM item indvidually to get its child and set back to main item.
            List<Item> LMSwihtouchild = mainItem.getItems().stream().filter(LM_Prdicate).collect(Collectors.toList()); 

            LMSwihtouchild.forEach(lmWihtoutChild -> {
                getItem(lmWihtoutChild.getId()) // here I am calling recursively to get the LM Item so that it will come with children
                .flatMap(lmWithChildren -> {
                    mainItem.getItems().removeIf(item -> item.getId().equals(lmWihtoutChild.getId())); // removing the LM item with out child from main item
                    mainItem.getContentItems().add(lmWithChildren); //Adding LM item with Children
                    return Mono.just(mainItem);
                })
                .subscribe()             
            });
            return Mono.just(mainItem); // This retruning to as  response before calling and getting the LM items with children.
        });
}

【问题讨论】:

    标签: spring-boot recursion spring-webflux project-reactor spring-webclient


    【解决方案1】:

    你需要制作方法链。你不应该在.flatMap 中执行.subscribe(),因为它没有连接到你的主方法链。

    我已经按照你的例子做了伪代码。

    getFullItem(itemId) {
        return getItem(itemId)
            .flatMap(mainItem -> {
                Predicate<Item> LM_Prdicate = p -> p.getItemType().equals(LM);
                List<Item> LMSwihtouchild = mainItem.getItems().stream().filter(LM_Prdicate).collect(Collectors.toList()); 
    
                // make flux from List<Item>. It's connected to your method chain.
                return Flux.fromIterable(LMSwihtouchild)
                    .flatMap(child -> getItem(child.getId())
                    .collectList()
                    .map(childList -> {
                        // merge result here
                        mainItem.getItems().removeIf(item -> item.getId().equals(lmWihtoutChild.getId()));
                        mainItem.getContentItems().add(lmWithChildren);
                        return mainItem;
                    }      
                });
            });
    }
    

    【讨论】:

    • 这工作得很好,但是如果我使用并行运行通量,则不支持 collectList,或者是否有任何其他方式可以并行运行通量并将项目收集到列表中以进行合并。
    • 我们需要在使用并行通量时使用自定义收集器。再次感谢。
    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多