【发布时间】:2021-03-10 21:12:56
【问题描述】:
我有下面的方法,我调用了几个 ReactiveMongoRepositories 来接收和处理某些文档。由于我是 Webflux 的新手,所以我边走边学。
我觉得下面的代码效率不高,因为我同时打开了多个流。这种编写代码的非阻塞方式使得从流中获取值并在后续的级联平面图中重用该值变得复杂。
在下面的示例中,我必须调用 userRepository 两次,因为我希望用户在开始时和之后。是否有可能使用 Webflux 更有效地做到这一点?
public Mono<Guideline> addGuideline(Guideline guideline, String keycloakUserId) {
Mono<Guideline> guidelineMono = userRepository.findByKeycloakUserId(keycloakUserId)
.flatMap(user -> {
return teamRepository.findUserInTeams(user.get_id());
}).zipWith(instructionRepository.findById(guideline.getInstructionId()))
.zipWith(userRepository.findByKeycloakUserId(keycloakUserId))
.flatMap(objects -> {
User user = objects.getT2();
Instruction instruction = objects.getT1().getT2();
Team team = objects.getT1().getT1();
if (instruction.getTeamId().equals(team.get_id())) {
guideline.setAddedByUser(user.get_id());
guideline.setTeamId(team.get_id());
guideline.setDateAdded(new Date());
guideline.setGuidelineStatus(GuidelineStatus.ACTIVE);
guideline.setGuidelineSteps(Arrays.asList());
return guidelineRepository.save(guideline);
} else {
return Mono.error(new InstructionDoesntBelongOrExistException("Unable to add, since this Instruction does not belong to you or doesn't exist anymore!"));
}
});
return guidelineMono;
}
【问题讨论】:
-
我没有 IDE,所以无法编写示例,但您可以从获取指令开始。保留
Mono<Instruction>,然后获取User和flatMap用户并获取团队,然后flatMap团队并构建一个由Mono<Tuple<User, Team>>组成的Mono<tuple>。然后你拿你的 2Monos并使用zipWith和combinatorprojectreactor.io/docs/core/release/api/reactor/core/publisher/… 并构建一个Mono<Tuple<User, Team, Instruction>>,你可以在上面进行平面映射。 -
所以基本上取 2,然后取 1,然后组合成 3。您可以使用
Tuples.of(...)函数创建元组 -
基本上是要写给你@Toerktumlare 的建议。从他的描述中猜你应该可以做到。
-
@p.streef 如果您愿意,请继续写一个答案。我目前没有 IDE 来写东西。但是,如果您觉得自己想要,那没问题。
-
@Toerktumlare 非常感谢。这似乎在提高效率和可读性方面起到了作用。我正在采取的方法是朝着正确的方向,所以这也证实了这一点。非常感谢。我注意到的是,所有这些流都是用 MongoDB 开放的,与阻塞编程相比,MongoDB 需要大量连接到数据库。仍然需要对此进行调查,因为连接似乎堆积起来并且没有迅速关闭。
标签: spring spring-mvc spring-webflux project-reactor