简体   繁体   English

带有文本/html 响应的响应式 WebClient GET 请求

[英]Reactive WebClient GET Request with text/html response

Currently I'm having an issue with new Spring 5 WebClient and I need some help to sort it out.目前我遇到了新的 Spring 5 WebClient 问题,我需要一些帮助来解决这个问题。 The issue is:问题是:

I request some url that returns json response with content type text/html;charset=utf-8 .我请求一些 url 返回内容类型为text/html;charset=utf-8 的json 响应。

But unfortunately I'm still getting an exception: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/html;charset=utf-8' not supported .但不幸的是,我仍然遇到异常: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/html;charset=utf-8' not supported So I can't convert response to DTO.所以我无法将响应转换为 DTO。

For request I use following code:对于请求,我使用以下代码:

Flux<SomeDTO> response = WebClient.create("https://someUrl")
                .get()
                .uri("/someUri").accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToFlux(SomeDTO.class);

response.subscribe(System.out::println);

Btw, it really doesn't matter which type I point in accept header, always returning text/html.顺便说一句,我在 accept header 中指向哪种类型并不重要,总是返回文本/html。 So how could I get my response converted eventually?那么我怎样才能最终转换我的回复呢?

If you need to set the maxInMemorySize along with text/html response use:如果您需要设置 maxInMemorySize 以及 text/html 响应,请使用:

  WebClient invoicesWebClient() {
    return WebClient.builder()
        .exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
        .build();
  }

  private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
    clientCodecConfigurer.defaultCodecs().maxInMemorySize(BUFFER_SIZE_16MB);
    clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
    clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
  }

Having a service send JSON with a "text/html" Content-Type is rather unusual. 让服务发送带有"text/html" Content-Type的JSON是非常不寻常的。

There are two ways to deal with this: 有两种方法可以解决此问题:

  1. configure the Jackson decoder to decode "text/html" content as well; 还配置Jackson解码器以解码"text/html"内容; look into the WebClient.builder().exchangeStrategies(ExchangeStrategies) setup method 查看WebClient.builder().exchangeStrategies(ExchangeStrategies)设置方法
  2. change the "Content-Type" response header on the fly 快速更改“ Content-Type”响应标头

Here's a proposal for the second solution: 这是第二种解决方案的建议:

WebClient client = WebClient.builder().filter((request, next) -> next.exchange(request)
                .map(response -> {
                    MyClientHttpResponseDecorator decorated = new 
                        MyClientHttpResponseDecorator(response); 
                    return decorated;
                })).build();

class MyClientHttpResponseDecorator extends ClientHttpResponseDecorator {

  private final HttpHeaders httpHeaders;

  public MyClientHttpResponseDecorator(ClientHttpResponse delegate) {
    super(delegate);
    this.httpHeaders = new HttpHeaders(this.getDelegate().getHeaders());
    // mutate the content-type header when necessary
  }

  @Override
  public HttpHeaders getHeaders() {
    return this.httpHeaders;
  }
}

Note that you should only use that client in that context (for this host). 请注意,您仅应在该上下文中(对于此主机)使用该客户端。 I'd strongly suggest to try and fix that strange content-type returned by the server, if you can. 如果可以的话,我强烈建议您尝试修复服务器返回的那种奇怪的内容类型。

As mentioned in previous answer, you can use exchangeStrategies method, 如上一个答案所述,您可以使用exchangeStrategies方法,

example: 例:

            Flux<SomeDTO> response = WebClient.builder()
                .baseUrl(url)
                .exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
                .build()
                .get()
                .uri(builder.toUriString(), 1L)
                .retrieve()
                .bodyToFlux( // .. business logic


private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
    clientCodecConfigurer.customCodecs().encoder(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
    clientCodecConfigurer.customCodecs().decoder(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM