org.springframework.web.reactive.function.UnsupportedMediaTypeException: 请求的Content-Type为'text/xml;charset=UTF-8',不支持该类型的请求体。

16

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

尝试使用Spring WebClient来消费返回XML且内容类型为"text/xml;charset=UTF-8"的Web服务端点。

项目的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] at 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] at org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$2(BodyExtractors.java:85) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:95) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at 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'


2
Jackson 用于处理 JSON。你需要使用 JAXB 来处理 XML。 - Kartik
你可以尝试使用application/xml作为Content-Type的值来发送XML站点地图。 - Steve Nash
@guilhebl,我仍然遇到这个错误。你找到解决方法了吗? - user1578872
5个回答

5
目前,Spring Framework还不支持Jackson XML - 请查看专门的问题。同时,您可以使用Jaxb并结合Jaxb2XmlEncoderJaxb2XmlDecoder来实现相应功能。

2
添加
.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) 

对我有帮助。 MediaType代表HTTP规范中定义的互联网媒体类型。 参考链接: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());
    }

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

1

我曾遇到类似的情况,当我尝试返回 "plain/text" 时,对象被解析为 json 格式(不是真正的文本)。我猜想 Spring 在验证响应内容类型和设置的正文时进行了一些验证。我的实际响应如下:

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

-1
另一种情况下,会抛出UnsupportedMediaTypeException异常,这可能会让人感到困惑。假设有一个生产API,它同时监听http/80和https/443端口。但是,它被配置为不通过http提供任何内容。相反,它返回一个带有content-type text/html的HTTP 301重定向消息和一些HTML内容。默认情况下,WebClient不会遵循301重定向,而是尝试将返回的HTML消息解析为假定的类。显然,这会失败并产生UnsupportedMediaTypeException异常。这可能会进一步混淆事情,因为Postman默认会透明地跟随301重定向。这会给人留下印象,认为您可以通过HTTP请求获取预期的内容。
解决方案:使用HTTPS请求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接