【问题标题】:Spring WebFlux: Perform multiple mappings on the same object?Spring WebFlux:对同一个对象执行多个映射?
【发布时间】:2021-04-09 07:24:57
【问题描述】:

我目前正在使用 Spring WebFlux 制作我的第一个响应式项目。不幸的是,我已经分配了一个我似乎找不到解决方案的任务。 我想收到一个 Mono 并对其执行操作,具体取决于其他 Monos 完成的内容。我的想法是这样的:

private Mono<ResourceModel> setResourcesIfExisting(String resourceName) {
        
        return resourceService.findByFilter(resourceName)
                .flatMap(res -> service1.findByFilter(resourceName).map(res::setResource))
                .flatMap(res -> service2.findByFilter(resourceName).map(res::setResource))
                .flatMap(res -> service3.findByFilter(resourceName).map(res::setResource))
                ;
    }

resourceService 会找到一个 Mono,注意这已经是我想要返回的相同类型了。但是现在,我有一些其他服务可以提供资源,理论上应该在所有这些服务中都有一个满足资源单。 从我的测试来看,如果我使用其中一个 flatMaps,它总是有效,但是只要我连续两个或多个在更高级别方法上收集的列表结果为空(我对 @987654322 的每个元素使用上述方法@)。

有人能告诉我为什么会发生这种情况吗?如上所述,我几乎不明白自己在做什么,但尝试了很多,但到目前为止没有成功。

【问题讨论】:

  • 我不太明白你的问题in therory there should be exactly one fulfilling resource mono across all of those services 你说的fulfilling 是什么意思。 but as soon as I have two or more 我猜你的意思是两个或更多 flatMapsflatMap 将获取一个项目,然后将该项目作为Mono&lt;T&gt; 返回到链中的下一个flatMap。我认为如果您扩展您的示例并提供解释所有这些service1.findByFilter 做什么以及res.setResource 做什么的代码会更好。你的意图是什么。
  • 当我们没有完全运行的示例时,很难给你任何指示。
  • @Toerktumlare 我的意思是一个Mono,它实际上拥有一个值,因为Mono 最多只能包含一个对象。对不起,如果这是一个不正确的术语。基本上我希望service1service2service3 中的一个返回一个值。是的,“两个或更多”意味着两个或更多flatMaps。 'findByFilter' 方法每个都返回他们从数据库中获取的模型,而 'setResource' 方法是基本的设置器。他们旨在将他们收到的模型设置为来自resourceServiceResourceModel
  • mapflatMap 需要返回值。反应式编程从函数式编程中获取了很多基础知识,这意味着要避免可变性。这意味着使用 setter 操作创建的对象不是您应该做的事情,因为它会给您带来很多问题。因此,由于我没有您的代码的全貌,因此实际上很难给您任何建议,但是如果您想改变它,您需要通过 flatMaps 传递您的 res 类。这也意味着在你获取新数据后,你需要传递res对象

标签: java spring rest spring-webflux


【解决方案1】:

上述输出的原因就是这个。

  • 假设您从非resourceService.findByFilter(resourceName) 获得Mono&lt;ResourceModel&gt;
  • 但在第一个 .flatmap 之后调用 service1.findByFilter(resourceName) 可能会返回 empty
  • 返回空后,不会调用其他flatmap,因为不会返回任何元素,因为每个元素都会调用flatmap

或者,您可以使用以下方法来实现您的预​​期

private Mono<ResourceModel> setResourcesIfExisting(String resourceName) {

    return resourceService.findByFilter(resourceName)
            .flatMap(res -> service1.findByFilter(resourceName)
                    .switchIfEmpty(service2.findByFilter(resourceName))
                    .switchIfEmpty(service3.findByFilter(resourceName))
                    .doOnEach(stringSignal -> res.setResource(stringSignal.get()))
                    .thenReturn(res));
}

thenReturn 将返回 ResourceModel,即使所有 service1、2、3 都返回空。

【讨论】:

  • 感谢您的回答!不再需要它,因为这是很久以前提出的,但我确信这正是我当时所需要的。如果我遇到类似的情况,我期待使用它!
猜你喜欢
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
相关资源
最近更新 更多