WebClient 上的阻止调用无限期挂起

Blocking calls on WebClient hangs indefinitely

我有三个 WebClient,看起来像这样:

WebClient

public Mono<MyObject> getResponseOne() {
    return webClient.get()
        .uri(URI) 
         .header("header", header)
        .bodyValue(body)
        .retrieve()
        .bodyToMono(MyObject.class);
}

然后我有一个调用多个 WebClient 的控制器:

控制器

@ResponseBody
@PostMapping("/get")
public Mono<MyObject> processResponse() {
    MyObject obj = getResponseOne().toFuture().get();
    system.out.println("Got first response");

    String str = getResponseTwo().toFuture().get();
    system.out.println("Got second response");

    //process and send with third WebClient
    MyObject newObj = getResponseThree(obj, str).toFuture().get();

    //process response from third WebClient and send to fourth WebClient
    //return statement

}

当我调用 /get 时,控制台只打印 "Got first response" 然后就停在那里,下面的任何内容似乎都没有执行。我正在使用 Postman 发送请求,所以它一直在等待而没有得到任何响应。

这可能相关也可能不相关,但我正在使用阻塞调用,因为我需要在将其发送到第三个 WebClient 之前处理两个响应,来自第三个 WebClient 的响应也将在之前进行额外处理作为 processResponse().

的响应返回

解决方案

我按照亚历克斯的建议使用了 Mono.zip()

@ResponseBody
@PostMapping("/get")
public Mono<MyObject> processResponse() {
    //TupleN depends on the amount of Monos you want to process
    Mono<Tuple2<MyObject,String>> output = Mono.zip(getResponseOne(),getResponseTwo());

    return output.map(result ->{
        // getT1() & getT2() is automatically generated by the tuple
        MyObject obj = result.getT1();
        String str = result.getT2();
    
        getResponseThree(obj, str);

        //process and return
    });
}

更多关于Mono.zip()

反应式 API 在您订阅之前什么都不会发生。您的方法 returns Mono 并且您需要构建一个流合并发布者。根据需要的逻辑,有多种组合方式。

例如,如果您需要前任的结果,您可以使用 flatMap 依次解析 Mono

return getResponseOne()
    .flatMap(res -> getResponseTwo(res))
    .flatMap(res -> getResponseThree(res));

如果调用是独立的,您可以使用 then

return getResponseOne()
    .then(getResponseTwo())
    .then(getResponseThree());

您也可以使用 Mono.when(getResponseOne(), getResponseTwo(), getResponseThree())Mono.zip(getResponseOne(), getResponseTwo(), getResponseThree()).

并行执行

还有许多其他运算符,但这里的关键是构建流和 return MonoFlux.