Spring Webflux WebClient

Posted

技术标签:

【中文标题】Spring Webflux WebClient【英文标题】: 【发布时间】:2018-05-09 01:13:32 【问题描述】:

我真的不知道如何正确地将以下调用转换为 spring webflux webclient。

userIds 是列表,我可以使用以下语法调用该服务,但我无法使用 Spring WebFlux WebClient 进行调用。如果有谁知道怎么做,请帮助我。

String url = "http://profile.service.com/v1/profiles/bulk";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

ResponseEntity<List<MiniProfile>> responseEntity;
try 
    responseEntity = restTemplate.exchange(url, HttpMethod.POST, new 
    HttpEntity(userIds, headers), new 
    ParameterizedTypeReference<List<MiniProfile>>() );
 catch (RestClientException e) 
    responseEntity = new ResponseEntity<List<MiniProfile>>(HttpStatus.OK);


return responseEntity.getBody();

这是我将它转换为 Webflux WebClient 的方式:

Flux<String> flux = Flux.fromIterable(userIds);
return readWebClient.post().uri("/v1/profiles/bulk")
      .body(BodyInserters.fromPublisher(flux, String.class))
      .retrieve().bodyToFlux(MiniProfile.class);

【问题讨论】:

您当前的解决方案有什么问题?你得到什么结果?你期待的是什么? 我收到一个 500 错误代码,我不知道它来自哪里,这里是堆栈跟踪。 org.springframework.web.reactive.function.client.WebClientResponseException:ClientResponse 有错误的状态代码:500 内部服务器错误。我希望我们的服务返回一个配置文件列表。请注意带有 RestTemplate 的旧代码对我来说效果很好。 这是属于您的问题的重要信息,真的。这表示服务器使用 HTTP 500 进行响应。因此 RestTemplate 和 WebClient 之间的请求必须不同。 我同意 RestTemplate 和 WebClient 之间的请求必须不同。我一直在尝试查看它们之间的请求是否不同,但我只能看到 RestTemplate 的请求正文被翻译为这样的字符串数组 ["0449b652-0006-0000-0000-000000000000", "0333b652- 0006-0000-0000-000000000000"] 与我们的依赖服务配合得很好,但我无法将 Netty WebClient 中的请求视为像 RestTemplate 这样的 json 格式,所以我不知道有什么区别。你知道如何在 Netty WebClient 中看到序列化的请求正文吗? 您可以像这样设置日志记录级别:logging.level.reactor.ipc.netty.channel.ContextHandler=debug logging.level.reactor.ipc.netty.http.client.HttpClient=debug 在您的application.properties 文件中 【参考方案1】:

您不应该将您的列表更改为flux,您应该像这样将其作为列表发送

return readWebClient.post()
  .uri("/v1/profiles/bulk")
  .syncBody(userIds)
  .retrieve()
  .bodyToFlux(new ParameterizedTypeReference<List<MiniProfile>>() )
  .flatMapIterable(Function.identity());

此代码未经测试,但原理相同

【讨论】:

感谢您抽出宝贵时间回答我的问题,但您的代码或我的代码没有任何问题,但当我们使用 Webflux Webclient 在 .NET 堆栈上放置或发布时,真正的问题出在我们的 .NET 堆栈上我们需要在 .NET 堆栈中处理原始请求。【参考方案2】:

使用.bodyValue(userIds).syncBody(userIds)(已弃用)代替带有主体插入器的主体

【讨论】:

【参考方案3】:

**你可以参考下面提到的代码sn-ps **

WebClient.post().uri(endPointUrl)
           .contentType(MediaType.APPLICATION_XML)
          .body(Mono.just(xmlEntity), String.class)
          .retrieve()

【讨论】:

【参考方案4】:

最好使用 WebClient 进行这样的响应式调用。

@Autowired
private WebClient.Builder webClientBuilder;
webClientBuilder.build().post()
                .uri("http://profile.service.com/v1/profiles/bulk")
                .body(BodyInserters.fromPublisher(Mono.just(new YourBodyClass()),YourBodyClass.class))
                .headers(httpHeaders -> 
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
                )
                .retrieve().bodyToFlux(MiniProfile.class);

【讨论】:

以上是关于Spring Webflux WebClient的主要内容,如果未能解决你的问题,请参考以下文章

Spring Webflux - 03 Webflux编程模型

Spring-WebFlux使用,一文带你从0开始学明白Spring-WebFlux,学明白响应式编程

Spring WebFlux

Spring @Async 与 Spring WebFlux

深入剖析 Spring WebFlux

Spring 5 之 WebFlux 开发反应式 Web 应用