首页 > 解决方案 > 如何在 WebFlux 控制器中订阅

问题描述

在 REST 控制器中,我需要调用 REST 来获取一个值,该值将用作第二个 REST 调用的 URI 变量。

@PostMapping
public void abbina(@RequestBody DocumentsUploadRequest documentsUploadRequest) {

  Mono<GetResult> result = WebClient
      .create(url)
      .get()
       .....
      .retrieve()
      .bodyToMono(GetResult.class)
      ;

  WebClient.post()
      .uri(...)
      .path("/{partita}")
      .build(result.block().getValue()))
      .....
      .bodyToMono(PostResult.class)
   ....
}

问题是 WebFlux REST 在单声道/通量上不可能调用块。

代码抛出

java.lang.IllegalStateException block()/blockFirst()/blockLast() 是阻塞的,线程reactor-http中不支持

我试图改变

.build(result.block().getValue()))

.build(result.share().block().getValue()))

但现在问题是result.share().block()无限期挂起。

标签: javaspring-webfluxproject-reactorspring-webclientwebflux

解决方案


首先,您永远不应该在反应式管道中阻塞。您应该订阅。在这种特殊情况下,只要您提供发布者,Spring Webflux 框架就会为您订阅。为此,控制器方法必须Mono像这样返回您的发布者:

@PostMapping
public Mono<Void> abbina(@RequestBody Attribute documentsUploadRequest) {

}

在这里,Mono<Void>您的发布者将完成的定义没有任何价值。

然后你必须建立一个没有阻塞的反应管道。

第一次 HTTP 调用的结果MonoGetResult

private Mono<GetResult> getResult() {
    return WebClient
            .get()
            //...
            .retrieve()
            .bodyToMono(GetResult.class);
}

同样,第二个 HTTP 调用返回 a Monoof PostResult

private Mono<PostResult> postResult(String firstResult) {
    return WebClient
            .post()
            //...
            .retrieve()
            .bodyToMono(PostResult.class);
}

最后,结合这两个发布者以使用flatmap操作符构建您的管道:

@PostMapping
public Mono<Void> abbina(@RequestBody Attribute documentsUploadRequest) {
    return getResult()
            .flatMap(result -> postResult(result.getValue()))
            .then();
}

我建议查看以下指南:构建反应式 RESTful Web 服务


推荐阅读