【问题标题】:WebFlux - how to check if Mono<ResponseEntity<Flux<MyItem>>> is empty to return 404WebFlux - 如何检查 Mono<ResponseEntity<Flux<MyItem>>> 是否为空以返回 404
【发布时间】:2020-05-06 23:54:25
【问题描述】:

我的代码:

public Mono<ResponseEntity<Flux<TreeItem>>> allGroups(
      @PathVariable(value = "email") String email, ServerWebExchange exchange) {

    return Mono.just(
            userGroupService
                .findGroupByEmail(email) //Flux<GroupById>
                .flatMap(getGroups(email)) //Flux<TreeItem>
                .map(TreeItem::getId) //Flux<UUID>
                .collectList() //Mono<List<UUID>>
                .flatMap(getFilteredGroupIdsForUserPrivilege())
                .flatMapMany(Flux::fromIterable) //Flux<UUID>
                .flatMap(getUserTreeGroups(email)))
        .map(ResponseEntity::ok)
        .defaultIfEmpty(ResponseEntity.notFound().build()); --> is not executed at all when no data are returned

当我传递不存在的电子邮件时,我的代码返回带有空数组的响应 200:[]

在这种情况下,我想返回404 error - 为什么最后一行没有执行?

.defaultIfEmpty(ResponseEntity.notFound().build());

getUserTreeGroups 方法:

private Function<UUID, Publisher<? extends TreeItem>> getUserTreeGroups(String email) {
    return filteredGroupId -> userGroupService
        .findUserTreeGroup(filteredGroupId, email);
  }

和方法findUserTreeGroup:

public Mono<GroupTreeItem> findUserTreeGroup(UUID groupId, String email) {
    return groupByIdRepo.findById(groupId)
            .flatMap(group -> findChildData(email, group));
  }

我想向前端返回一个 TreeItem 列表。 老实说 - 我仍然不明白何时使用 Mono&lt;ResponseEntity&lt;Flux&lt;TreeItem&gt;&gt;&gt;Mono&lt;ResponseEntity&lt;List&lt;TreeItem&gt;&gt;&gt;?有什么区别?

更新 应用 Thomas Andolf 的解决方案后:

public Mono<ResponseEntity<Flux<TreeItem>>> userAllTreeGroups(
    @PathVariable(value = "email") String email, ServerWebExchange exchange) {
    return userGroupService
              .findUserGroupByEmail(email) //Flux<GroupById>
              .flatMap(groupById -> userGroupService.findUserTreeGroup(groupById.getId(), email)) //Flux<TreeItem>
              .map(TreeItem::getId) //Flux<UUID>
              .collectList() //Mono<List<UUID>>
              .flatMap(groupIds ->
                  rolePrivilegesService.filterGroupIdsForUserPrivilege(groupIds, GROUP_USER_READ_PRIVILEGE))
              .flatMapMany(Flux::fromIterable) //Flux<UUID>
              .flatMap(filteredGroupId -> userGroupService.findUserTreeGroup(filteredGroupId, email)) //Flux<GroupItem>
              .collectList() //Mono<List<TreeItem>>
              .map(ResponseEntity::ok) //Mono<ResponseEntity<List<TreeItem>>>
              .defaultIfEmpty(ResponseEntity.notFound().build());

但我仍然必须返回 Mono>>。

你认为我的方法应该返回什么? Mono>> 喜欢在您的解决方案中???

【问题讨论】:

  • 能不能加个.log操作符分享日志?
  • 你为什么要把所有东西都放在Mono.just 中? getUserTreeGroups(email) 返回什么?你能发布这段代码吗
  • A 更新了我的帖子,添加了 1 个方法的实现。我想返回一个 List
  • 这次你能不能真正包含我认为很明显的东西,findUserTreeGroup 的实现,因为你提供的代码只是一个毫无意义的高级函数。
  • 添加了 findUserTreeGroup 的实现

标签: java reactive-programming spring-webflux


【解决方案1】:

在我的第二条评论中,我问了

为什么要将所有内容都放入Mono.just()

你没有回答,好吧,如果你真的读过它,那将解决它,因为这可能是你的问题。

final List<String> strings = Collections.emptyList();

// You are wrapping a flux in a mono for some strange reason?
final Mono<Flux<String>> wrappedFlux = Mono.just(Flux.fromIterable(strings)
        .flatMap(s -> Mono.just("This never gets run"))
).defaultIfEmpty(Flux.just("This never gets run either, because there is a flux in the mono"));

重写

// Can't test it but something in the lines of the following
return userGroupService
            .findGroupByEmail(email) //Flux<GroupById>
            .flatMap(getGroups(email)) //Flux<TreeItem>
            .map(TreeItem::getId) //Flux<UUID>
            .collectList() //Mono<List<UUID>>
            .flatMap(getFilteredGroupIdsForUserPrivilege())
            .flatMapMany(Flux::fromIterable) //Flux<UUID>
            .flatMap(getUserTreeGroups(email)))
            .collectList()
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

Mono&lt;T&gt; 将持有一个未来的计算。当有人订阅它时,它会尝试解析其中的内容,当它的内部状态变为COMPLETED时,它会射出它。

Flux&lt;T&gt; 是同一件事,但适用于许多对象。你可以想如果它和以前一样多Mono&lt;T&gt;s,当有人订阅它时,它会尝试解决Flux&lt;T&gt;中每个项目中的问题,并在状态达到@987654330时立即弹出这些问题@每个人。

在您订阅 Mono&lt;T&gt; or aFlux 之前,什么都不会发生。

如果您订阅时有Mono&lt;Flux&lt;T&gt;&gt;,它会尝试解析其中的任何内容,而其中的内容是Flux&lt;T&gt;,因此会被直接枪杀。

另一方面,Flux&lt;T&gt; 没有人订阅,因此其中没有任何内容得到解决。基本上是死的、空的、没用过的。

你在问我:

所以在您看来,在 Mono 中使用 Flux 毫无意义/毫无意义

我刚刚在上面写了反应式编程如何工作的绝对基础。您正在从没有人订阅的 Mono&lt;T&gt; 发出 Flux&lt;T&gt;

除非您订阅,否则什么都不会发生。

我建议你从一开始就阅读reactor的文档,这对理解reactive programming的基本概念很有帮助

我不知道你想要达到什么目标,因为我没有你的完整代码库,我不知道你要返回什么。

【讨论】:

  • 感谢您的回答-我将所有内容都包装在 Mono 中,因为我使用 openapi 生成端点,而 openapi 生成的每个端点都返回类似 Mono? Mono>> 呢?应用您的解决方案后,我得到了最终类型 Mono>> - 我无法更改方法返回类型...而且我认为要返回 ResponseEntity 我必须返回 Mono... 请看看我的更新
  • 不,我无法帮助您,因为我不知道您的返回类型是什么以及您在做什么,而且您似乎也不知道任何线索。请阅读反应式编程的基础知识 堆栈溢出不是您学习反应式编程的地方。我已经回答了你的问题。如果您需要更多帮助,请生成一个最小的可重现示例。这证明了你的问题。
  • 并停止更新您的任务。我已经回答了你的问题。如果您想知道Mono&lt;List&lt;T&gt;&gt;Flux&lt;T&gt; google 之间的区别,这里有几个答案。
  • 你是对的,也许我的情况太复杂了,另一方面我不想复制我的数千行代码......无论如何,感谢宝贵的提示,现在我知道了问题出在哪里
  • 这不是“太复杂”,而是你问了5个问题,“这个,这个,那个,我该怎么做,我不知道,这个那个那个,还有我应该这样做还是这样或有什么区别?”您的问题中有 80% 记录在官方反应堆文档中。如果您有更多问题,请阅读官方文档。从小处着手,当您了解概念并遇到问题时,创建一个可重复的小示例并提出一个非常具体的问题。不是“这是我巨大的代码库,它不起作用,求助”。
【解决方案2】:

简单来说,您可以像这样编写您的退货声明

return Mono.just(ResponseEntity.ok(yourService.yourMethod()));

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 2018-02-04
    • 2022-12-23
    • 2021-11-03
    • 2021-03-25
    • 2018-04-24
    • 2021-03-15
    • 2018-12-19
    • 2019-04-25
    相关资源
    最近更新 更多