英文:
Spring Webflux How to do call 2 different services sequentially without blocking?
问题
我遇到了与WebFlux有关的问题。
让我描述一下我想要同步执行的内容。
首先,我想要将产品保存到数据库并获得生成的ID。
接下来,我想要保存产品的评论,带有产品ID。
我希望能在一个微服务控制器的单个服务调用中完成这些操作。我不清楚在没有阻塞的情况下如何在控制器中实现这一点(我知道这是不应该做的事情)。
我将数据发送到我的RestController,如下所示:
{
"name": "product 1",
"weight": 5,
"reviews": [
{
"rating": 5,
"post": "review post"
},
{
"rating": 10,
"post": "Second review post"
}
]
}
public class MyService {
// 这将调用另一个微服务并返回带有保存的产品的Mono
public Mono<Product> saveProduct(Product product) { ... }
// 这将调用另一个微服务来保存评论
public Mono<Void> saveReview(Review review) { ... }
}
@RestController
public class MyController {
@Autowired
MyService service;
@PostMapping("/composite-product")
public Mono<Void> saveCompositeProduct(CompositeProduct cp) {
// 此时id为空
Product product = new Product(cp.getName(), cp.getWeight());
return service.saveProduct(product)
.flatMapMany(savedProduct -> {
if(cp.getReviews() == null) return Flux.empty();
// 我向评论添加产品id
List<Review> reviews = cp.getReviews().stream()
.map(review -> new Review(savedProduct.getId(), review.getRating(), review.getPost()))
.collect(Collectors.toList());
// 我尝试保存评论,但不起作用,因为没有任何东西订阅它。
// 我不想添加任何类型的subscribe方法或block方法,我知道在WebFlux应用程序中这样做是错误的
return Flux.fromIterable(reviews)
.flatMap(r -> service.saveReview(r));
}).then();
}
}
我该如何让这个工作起来?
英文:
I am having an issue with webflux
let me describe what I want to do synchronously.
First, I want to save a product to the db and get a generated ID
Next I want to save reviews of the product with productId.
I want to do this in one service call to the microservice controller. I do not see how this can be accomplished in controller without blocking (which I know is something I should not do)
I am sending data like the following to my restcontroller
{
name: "product 1",
weight: 5,
reviews: [
{
rating: 5,
post: "review post"
}, {
rating: 10,
post: "Second review post"
}]
}
public class MyService {
//This will call another micro-service and returns a Mono with the saved product
public Mono<Product> saveProduct(Product product) { ... }
//This will call another micro-service to save the review
public Mono<Void> saveReview(Review review) { ... }
}
@RestController
public class MyController {
@Autowired
MyService service;
@PostMapping("/composite-product")
public Mono<Void> saveCompositeProduct(CompositeProduct cp) {
// The id is null at this time
Product product = new Product(cp.getName(), cp.getWeight());
return service.saveProduct(product)
.flatMapMany(savedProduct -> {
if(cp.getReviews() == null) return Flux.empty();
// I add the product id to the review
List<Review> reviews = cp.getReviews().stream()
.map(review -> new Review(savedProduct.getId(), review.getRating(), review.getPost())
.collect(Collectors.toList());
// I try to save the reviews but it does not work because nothing ever
//subscribes to it. I do not want to add any type of subscribe method
// or block method which I know is wrong to have in a webflux application
return Flux.fromIterable(reviews)
.map(r -> service.saveReview(r));
}).then();
}
How can I make this work?
答案1
得分: 0
使用flatMap
而不是map
操作符。flatMap
内部像flatMapMany
一样订阅了Mono
,就像Flux
订阅一样。
return Flux.fromIterable(reviews)
.flatMap(r -> service.saveReview(r));
英文:
Use flatMap
instead of map
operator. flatMap
subscribes to Mono
internally just like flatMapMany
does to Flux
.
return Flux.fromIterable(reviews)
.flatMap(r -> service.saveReview(r));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论