![](/img/trans.png)
[英]How to combine Flux and ResponseEntity in Spring Webflux controllers
[英]WebFlux - how to check if Mono<ResponseEntity<Flux<MyItem>>> is empty to return 404
我的代码:
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
当我传递不存在的 email 时,我的代码返回响应 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<ResponseEntity<Flux<TreeItem>>>
或者Mono<ResponseEntity<List<TreeItem>>>
? 有什么不同?
更新应用 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>> 喜欢在您的解决方案中???
在我的第二条评论中,我问
为什么将所有内容都放入
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<T>
将持有一个未来的计算。 当有人订阅它时,它会尝试解析其中的内容,当它的内部状态变为COMPLETED
时,它会射出它。
Flux<T>
是同样的东西,但适用于许多对象。 你可以想,如果它和以前一样多Mono<T>
s,当有人订阅它时,它会尝试解决Flux<T>
中每个项目内部的问题,并在状态达到时立即弹出这些问题为每一个人COMPLETED
。
在您订阅Mono<T> or a
Flux` 之前,什么都不会发生。
如果您在订阅时有Mono<Flux<T>>
,它将尝试解析其中的任何内容,而其中的内容是Flux<T>
,因此将直接被射出。
另一方面, Flux<T>
没有人订阅,因此其中没有任何内容被解决。 它基本上是死的、空的、没有使用的。
你在问我:
因此,在您看来,在 Mono 中使用 Flux 毫无意义/毫无意义
我刚刚在上面写了反应式编程如何工作的绝对基础知识。 您正在从没有人订阅的Mono<T>
发出Flux<T>
。
除非您订阅,否则什么也不会发生。
我建议你从一开始就阅读反应器的文档,这对理解反应式编程的基本概念很有帮助
我不知道您要达到什么目的,因为我没有您的完整代码库,我不知道您要返回什么。
简单来说,您可以像这样编写返回语句
return Mono.just(ResponseEntity.ok(yourService.yourMethod()));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.