具有text / html响应的Reactive WebClient GET请求

时间:2018-01-31 23:40:03

标签: java spring reactive spring-webflux

目前我遇到了新的Spring 5 WebClient的问题,我需要一些帮助来解决它。 问题是:

  

我请求一些返回内容类型为 text / html; charset = utf-8 的json响应的网址。

     

但不幸的是我仍然得到一个例外:   的 org.springframework.web.reactive.function.UnsupportedMediaTypeException:   内容类型'text / html; charset = utf-8'不受支持。所以我不能   将响应转换为DTO。

对于请求,我使用以下代码:

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

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

顺便说一下,我在接受标题中指向哪种类型无关紧要,总是返回text / html。那我怎么能最终转换我的回复呢?

2 个答案:

答案 0 :(得分:0)

让服务发送带有"text/html"内容类型的JSON是相当不寻常的。

有两种方法可以解决这个问题:

  1. 配置Jackson解码器以解码"text/html"内容;查看WebClient.builder().exchangeStrategies(ExchangeStrategies)设置方法
  2. 动态更改“Content-Type”响应标题
  3. 以下是第二个解决方案的提案:

    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;
      }
    }
    

    请注意,您应该只在该上下文中使用该客户端(对于此主机)。 我强烈建议尝试修复服务器返回的奇怪内容类型,如果可以的话。

答案 1 :(得分:0)

如上一个答案所述,您可以使用exchangeStrategies方法,

示例:

            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));
}