【问题标题】:How to process Webclient response to HttpServletResponse?如何处理 Webclient 对 HttpServletResponse 的响应?
【发布时间】:2021-06-29 06:15:16
【问题描述】:

我们正在将我们的代码从 RestTemplate 移动到 WebClient 以实现非阻塞调用,我们几乎完成了。但是,在将我们的代码移动到 WebClient 之后,我们面临的问题是当客户端调用我们的 API 时,我们以空白响应进行响应。虽然,我们的后端客户端有响应。

我试过了,ofResponseProcessor,但这似乎没有执行(因为方法内部的日志没有被打印)

这是我的代码:

Mono<ClientResponse> clientResponse = WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(clientOptions))
                .filter(processResponse(httpResponse)) <-- passing HttpServletResponse
                .baseUrl("https://xxxxx.xxxx/")
                .build()
                .get()
                .uri("/getresult")
                .exchange();
logger.info("======Thread Completed=====");

现在,我们的 processResponse 会将响应从 ClientResponse 写入 HttpServletResponse

public ExchangeFilterFunction processResponse(HttpServletResponse resp) {
        return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
             logger.info("======Writing Response=====");
             writeResponse(clientResponse,resp); //writing response to servletresponse
             return Mono.just(clientResponse);
        });
    }

我在控制台日志中没有看到 ======Writing Response=====

我也尝试在ClientResponse 上使用subscribe,但在我输入Thread.sleep 之前,我仍然收到空白回复。

谁能帮助我了解我在这里缺少什么?

====更新=====

private void writeResponse(ClientResponse clientResponse, HttpServletResponse resp){

clientResponse.bodyToMono(String.class)
   .subscribe(consumer -> {
       ....
       ....
       IOUtils.copy(new ByteArrayInputStream(consumer.getBytes()),resp.getOutputStream());
    }
   ...
  );
}

【问题讨论】:

  • 您能否将代码发布在您使用 clientResponse 的位置以及如何返回响应?
  • @JArgente 添加了我正在写入 servletresponse 的部分代码

标签: java servlets reactive-programming spring-webflux spring-webclient


【解决方案1】:

由于您使用的是非阻塞调用,执行 API 调用(和订阅块)的线程与主线程不同,因此主线程将继续执行其余代码并返回响应,尽管其他线程还没完呢。

所以你有两个选项可以让你的 API 反应,这样你就可以直接返回 Mono 对象,并且是 API 的客户端订阅它,或者如果你想要同步(非反应)API,你必须调用Mono对象的block方法让主线程获取外部调用的结果

【讨论】:

  • 您能否分享第一种方法的示例代码,并将尝试。我的意思是,我应该在我的方法代码中更改什么?
  • 我在您的案例中看到的第一种方法的问题是您直接在 httpservletresponse 对象中编写,您没有返回其他前端或后端应用程序使用的 json 或其他对象。这是直接输出 HTML 代码的服务器端渲染应用程序吗?
  • 是的,这是服务器端渲染,输出/响应由客户端消耗。因此,基本上,我们从其他服务获取数据并呈现响应,然后为我们的客户端写入 servletresponse。
  • 那么在这种情况下你应该阻塞webclient响应以在主线程中获取响应并返回。
  • 这里的问题是您的 API 是同步的,因此您没有其他方法可以等到 weblclient 响应完成才能将结果返回给您的客户端。如果您需要进行其他外部调用并使它们并行或使用 map、filter、flatmap 等运算符在单声道中进行任何转换,您可以利用非阻塞功能。但最后您必须调用 block 来在主线程中获取结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多