【问题标题】:org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/xml;charset=UTF-8' not supported for bodyTypeorg.springframework.web.reactive.function.UnsupportedMediaTypeException:bodyType 不支持内容类型 'text/xml;charset=UTF-8'
【发布时间】:2019-11-23 18:34:35
【问题描述】:

使用 Java 11、SpringBoot 2、WebFlux、WebClient 和 Jackson

尝试使用 Spring WebClient 使用返回 XML 的 Web 服务端点,内容类型:'text/xml;charset=UTF-8'

项目的 pom.xml 中的 Jackson XML 依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.9</version>
</dependency>

触发对外部 API 的请求并构建响应的 WebClient 代码:

        WebClient.builder()
                .baseUrl(url)
                .build()
                .get()
                .uri(builder.toUriString(), 1L)
                .accept(TEXT_XML)
                .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML_VALUE)
                .acceptCharset(Charset.forName("UTF-8"))
                .exchange()
                .flatMap(x -> x.bodyToMono(ServiceResponse.class))
                .flatMap(x -> buildResponse(x));

ServiceResponse 类(一个简单的 POJO):

public class ServiceResponse {

    private String ack;
    private String version;
    private String timestamp;
// .. getters and setters

产生的错误:

org.springframework.web.reactive.function.UnsupportedMediaTypeException: 内容类型 'text/xml;charset=UTF-8' 不支持 bodyType=com.sample.service.model.ServiceResponse 在 org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] 在 java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na] at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:197) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] 在 org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$2(BodyExtractors.java:85) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] 在 org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:95) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] 在 org.springframework.web.reactive.function.client.DefaultClientResponse.bodyToMono(DefaultClientResponse.java:113) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE]

如何正确使用响应类型:Content-type 'text/xml;charset=UTF-8' ?

【问题讨论】:

  • 杰克逊适用于 JSON。您需要 JAXB 才能使用 XML。
  • 你可以试试 application/xml stackoverflow.com/questions/3272534/…
  • @guilhebl 我仍然面临这个错误。您找到解决方案了吗?

标签: java spring spring-boot jackson spring-webflux


【解决方案1】:

Spring Framework 目前不支持 Jackson XML - 请参阅 the dedicated issue。同时,您可以将 Jaxb 与 Jaxb2XmlEncoderJaxb2XmlDecoder 一起使用。

【讨论】:

    【解决方案2】:

    添加

    .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) 
    

    为我工作。 MediaType 表示 HTTP 规范中定义的 Internet 媒体类型。 供参考:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/MediaType.html

    当我尝试在 spring webflux 中使用 WebTestClient 编写 tc 时,我遇到了这个错误。 单元测试在以下部分:

    @Test
     public void testGetJobSummariesResBody() throws Exception{
     List<JobSummary> responseBody =
                    testClient
                    .get().uri("<uri-name>")
                    .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
                    .header(APPNAME_HEADER, "<header-name>")
                    .exchange()
                    .expectStatus().isOk()
                    .expectBodyList(JobSummary.class)
                    .returnResult()
                    .getResponseBody();
    
            assertNotNull(responseBody.get(0).getJobType());
            assertNotEquals(0,responseBody.size());
        }
    

    【讨论】:

      【解决方案3】:

      当我试图返回“纯文本”但对象被解析为 json 格式(因此不是真正的文本)时,我遇到了类似的情况。我想春天正在对你设置的响应内容类型和正文进行一些验证。我的实际反应是这样的:

      Mono.just(quote.getQuote())
                      .flatMap(s -> ServerResponse.ok()
                              .contentType(MediaType.TEXT_PLAIN)
                              .syncBody(s)
                      );
      

      但也可以接受的是:

      Mono.just(jsonQuote)
                      .flatMap(s -> ServerResponse.ok()
                              .contentType(MediaType.APPLICATION_JSON)
                              .syncBody(s)
                      );
      

      【讨论】:

        【解决方案4】:

        在我的情况下,问题是我忘记设置 Accept 标头,服务器的默认行为是返回 XML。
        将其设置为 MediaType.APPLICATION_JSON 解决了问题,服务器开始返回 JSON。

        【讨论】:

          【解决方案5】:

          另一种混淆 UnsupportedMediaTypeException 的情况被抛出。 让我们假设theres产生监听http/80和https/443的api。然而,它的配置使得没有内容通过 http 提供。相反,这会返回 HTTP 301 重定向消息,其中包含一些内容类型为 text/html 的 html 内容。默认情况下,WebClient 不遵循 301 重定向,而是尝试将返回的 html 消息解析为假定的类。这显然失败并产生 UnsupportedMediaTypeException 异常。 这可能会因为 Postman 默认遵循 301 重定向并以完全透明的方式进行这一事实而进一步混淆。给人的印象是您通过 http 请求获得了预期的内容。

          解决方案:使用 https 请求。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-02-15
            • 2015-03-26
            • 2014-09-18
            • 1970-01-01
            • 1970-01-01
            • 2018-07-24
            • 2017-09-01
            • 2012-01-05
            相关资源
            最近更新 更多