首页 > 解决方案 > 使用 Reactive webclient 递归调用 Mono 函数

问题描述

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

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

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

这是我的代码。发生的事情首先是我的 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-bootrecursionspring-webfluxproject-reactorspring-webclient

解决方案


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

我已经按照您的示例制作了伪代码。

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

推荐阅读