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

m13*_*rok 5 java spring reactive spring-webflux

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

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

但不幸的是,我仍然遇到异常: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/html;charset=utf-8' not supported。所以我无法将响应转换为 DTO。

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

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

response.subscribe(System.out::println);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我在接受标题中指向哪种类型并不重要,总是返回文本/html。那么我怎样才能最终转换我的回复呢?

gui*_*ebl 8

正如前面的回答中提到的,您可以使用 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));
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*zel 1

让服务发送带有"text/html"Content-Type 的 JSON 是相当不寻常的。

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

  1. 配置 Jackson 解码器来解码 "text/html"内容;查看WebClient.builder().exchangeStrategies(ExchangeStrategies)设置方法
  2. 动态更改“Content-Type”响应标头

这是第二个解决方案的建议:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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