我是项目反应堆的新手,在以下用例中很难找到一个干净的解决方案。
我的用例:
我想在数据库中保存一个新对象。如果对象已经存在于数据库中,那么我想发送一个错误响应,否则我想保存它并将保存的对象返回给客户端。
在受阻止的Web MVC应用程序中,代码如下所示:
@PostMapping("/cards")
public ResponseEntity<?> addCard(@RequestBody Card card) {
Card c = repo.findOneByWord(card.getWord());
if(c == null) {
Card savedCard = repo.save(card);
return ResponseEntity.ok(savedCard);
}
return ResponseEntity.unprocessableEntity().body("Card already exists");
}
我的非阻塞式webflux方法:
@PostMapping("/cards")
public Mono<ResponseEntity<?>> addCard(@RequestBody Card card) {
return repo.findOneByWord(card.getWord())
.map(c -> {
return new Card();
})
.switchIfEmpty(Mono.defer(() -> repo.save(card)))
.map(c -> {
if (c.getWord() == null) {
return ResponseEntity.unprocessableEntity().body("Card already exists.");
}
return ResponseEntity.ok(c);
});
}
代码工作正常,但可读性很差,感觉更像是一种解决方法...
关于如何使它更清晰/可读性的任何建议?
答案 0 :(得分:0)
我将通过以下方式重写该代码:
@PostMapping("/cards")
public Mono<ResponseEntity<?>> addCard(@RequestBody Card card) {
return repo.findOneByWord(card.getWord()) // (1)
.map(c -> // (2)
ResponseEntity.unprocessableEntity() // (2.1)
.body("Card already exists.") //
) //
.switchIfEmpty( // (3)
repo.save(card) // (3.1)
.map(c -> ResponseEntity.ok(c) // (3.2)
); //
}
Mono
。.map
,因此我们会将卡映射到422响应.map
函数,因此将订阅传递给.switchIfEmpty
的发布者。 注意,不必将后备Mono
(第3.1点)的创建包装到Mono.defer
中,因为只有在订阅给定流的情况下才会发生实际元素的存储。因此,由于仅在处理swithIfEmpty
时执行该执行,因此我们可以减少不必要的包装。最后,在点(3.2),结果将与存储的Card
对象映射到200响应。