如何在 WebFlux 控制器中订阅

How to subscribe inside a WebFlux Controller

在 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 内部不可能在 mono/flux 上调用块。

代码抛出

java.lang.IllegalStateException block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http

我试着改变

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

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

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

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

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

}

此处,Mono<Void> 定义您的发布商将完成而没有任何价值。

然后你必须构建一个无阻塞的反应管道。

第一个 HTTP 调用的结果是 Mono of GetResult:

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

同样,第二个 HTTP 调用 return 是 Mono of 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();
}

我建议您查看以下指南:Building a Reactive RESTful Web Service