为什么不能多次订阅发布者?

发布于 2025-01-10 11:57:35 字数 1289 浏览 0 评论 0原文

我写了两个方法,第一个方法仅调用发布者(productDtoMono)一次,另一个方法调用它两次, 从控制器调用时,第一个返回错误请求(空主体) 而第二个工作完美并返回 http ok 我做了功课,发现我不能多次使用出版商 这是为什么 ?

public Mono<ProductDto> firstupdateProduct(Mono<ProductDto> productDtoMono) {
    return productDtoMono.flatMap(productDto ->
            productRepository.findById(productDto.getId())
                    .flatMap(p -> productDtoMono
                            .map(EntityDtoUtil::toEntity)))
                    .flatMap(productRepository::save)
                    .map(EntityDtoUtil::toDto);
}
public Mono<ProductDto> secondupdateProduct(String id, Mono<ProductDto> productDtoMono) {
    return productRepository.findById(id)
            .flatMap(product -> productDtoMono
                    .map(EntityDtoUtil::toEntity))
            .flatMap(productRepository::save)
            .map(EntityDtoUtil::toDto);
}

我的控制器方法:

@PutMapping
public Mono<ResponseEntity<ProductDto>> updateProduct(@RequestBody Mono<ProductDto> productDtoMono){
    System.out.println("in controller "+productDtoMono);
    return productService.updateProduct(productDtoMono)
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

}

i wrote two methods,first one calls the publisher (productDtoMono) only once and the other one calls it twice,
the first one returns bad request (empty body) when called from controller
while the second works perfectly and returns http ok
i did my homework and i see that i can't consume the publisher more than one time
why is that ?

public Mono<ProductDto> firstupdateProduct(Mono<ProductDto> productDtoMono) {
    return productDtoMono.flatMap(productDto ->
            productRepository.findById(productDto.getId())
                    .flatMap(p -> productDtoMono
                            .map(EntityDtoUtil::toEntity)))
                    .flatMap(productRepository::save)
                    .map(EntityDtoUtil::toDto);
}
public Mono<ProductDto> secondupdateProduct(String id, Mono<ProductDto> productDtoMono) {
    return productRepository.findById(id)
            .flatMap(product -> productDtoMono
                    .map(EntityDtoUtil::toEntity))
            .flatMap(productRepository::save)
            .map(EntityDtoUtil::toDto);
}

my controller method :

@PutMapping
public Mono<ResponseEntity<ProductDto>> updateProduct(@RequestBody Mono<ProductDto> productDtoMono){
    System.out.println("in controller "+productDtoMono);
    return productService.updateProduct(productDtoMono)
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乜一 2025-01-17 11:57:35

我做了更多研究。 Mono、Flux默认是冷发布者,因此当它们的创建来源来自请求时,它们只能被消费一次。当我们尝试第二次使用它时,它会尝试从请求生成对象,因此会抛出错误的请求。我必须在将主体传递给服务时对其进行缓存,如下所示:

@PutMapping
public Mono<ResponseEntity<ProductDto>> updateProduct(@RequestBody Mono<ProductDto> productDtoMono){
    System.out.println("in controller "+productDtoMono);
    return productService.updateProduct(productDtoMono.cache())
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

}

并像这样更改了 updateProduct

public Mono<ProductDto> updateProduct(Mono<ProductDto> productDtoMono) {
    return productDtoMono.map(ProductDto::getId)
            .flatMap(productRepository::findById)
            .flatMap(product -> productDtoMono.map(EntityDtoUtil::toEntity))
            .flatMap(productRepository::save)
            .map(EntityDtoUtil::toDto);
}

I did more research. Mono, Flux are cold publishers by default, so when the source of their creation comes from a request, they can only be consumed once. When we try to consume it a second time, it tries to generate the object from a request, hence the bad request get thrown. I had to cache the body while passing it to service like this:

@PutMapping
public Mono<ResponseEntity<ProductDto>> updateProduct(@RequestBody Mono<ProductDto> productDtoMono){
    System.out.println("in controller "+productDtoMono);
    return productService.updateProduct(productDtoMono.cache())
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

}

and changed updateProduct like this

public Mono<ProductDto> updateProduct(Mono<ProductDto> productDtoMono) {
    return productDtoMono.map(ProductDto::getId)
            .flatMap(productRepository::findById)
            .flatMap(product -> productDtoMono.map(EntityDtoUtil::toEntity))
            .flatMap(productRepository::save)
            .map(EntityDtoUtil::toDto);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文