org.springframework.web.reactive.function.UnsupportedMediaTypeException: bodyType 不支持内容类型 'text/xml;charset=UTF-8'
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/xml;charset=UTF-8' not supported for bodyType
使用 Java11、SpringBoot 2、WebFlux、WebClient 和 Jackson
尝试使用 Spring WebClient 来使用 returns XML 的 Web 服务端点,内容类型:'text/xml;charset=UTF-8'
Jackson XML 项目中的依赖 pom.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 class(一个简单的 POJO):
public class ServiceResponse {
private String ack;
private String version;
private String timestamp;
// .. getters and setters
产生的错误:
org.springframework.web.reactive.function.UnsupportedMediaTypeException:
Content type 'text/xml;charset=UTF-8' not supported for
bodyType=com.sample.service.model.ServiceResponse at
org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders(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(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' ?
Spring 框架目前不支持 Jackson XML - 请参阅 the dedicated issue。同时,您可以将 Jaxb 与 Jaxb2XmlEncoder
和 Jaxb2XmlDecoder
.
一起使用
添加
.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());
}
我有一个类似的情况,当我试图 return "plain/text" 但对象被解析为 json 格式(所以不是真正的文本)。我想 spring 正在对响应 contenty-type 和你设置的正文进行一些验证。我的实际反应是这样的:
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)
);
在我的例子中,问题是我忘记设置 Accept
header 并且服务器的默认行为是 return XML.
将其设置为 MediaType.APPLICATION_JSON
解决了问题,服务器启动 returning JSON.
另一种情况是混淆时抛出UnsupportedMediaTypeException。
让我们假设生成 api 并同时监听 http/80 和 https/443。但是它的配置使得没有内容通过 http 提供。取而代之的是 returns HTTP 301 重定向消息,其中一些 html 内容的内容类型为 text/html。默认情况下,WebClient 不遵循 301 重定向,而是尝试将返回的 html 消息解析为假定的 class。这显然失败并产生 UnsupportedMediaTypeException 异常。
这可能会因为 Postman 默认遵循 301 重定向并以完全透明的方式进行而进一步混淆。给人的印象是您通过 http 请求获得了预期的内容。
解决方法:使用https请求。
使用 Java11、SpringBoot 2、WebFlux、WebClient 和 Jackson
尝试使用 Spring WebClient 来使用 returns XML 的 Web 服务端点,内容类型:'text/xml;charset=UTF-8'
Jackson XML 项目中的依赖 pom.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 class(一个简单的 POJO):
public class ServiceResponse {
private String ack;
private String version;
private String timestamp;
// .. getters and setters
产生的错误:
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/xml;charset=UTF-8' not supported for bodyType=com.sample.service.model.ServiceResponse at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders(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(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' ?
Spring 框架目前不支持 Jackson XML - 请参阅 the dedicated issue。同时,您可以将 Jaxb 与 Jaxb2XmlEncoder
和 Jaxb2XmlDecoder
.
添加
.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());
}
我有一个类似的情况,当我试图 return "plain/text" 但对象被解析为 json 格式(所以不是真正的文本)。我想 spring 正在对响应 contenty-type 和你设置的正文进行一些验证。我的实际反应是这样的:
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)
);
在我的例子中,问题是我忘记设置 Accept
header 并且服务器的默认行为是 return XML.
将其设置为 MediaType.APPLICATION_JSON
解决了问题,服务器启动 returning JSON.
另一种情况是混淆时抛出UnsupportedMediaTypeException。 让我们假设生成 api 并同时监听 http/80 和 https/443。但是它的配置使得没有内容通过 http 提供。取而代之的是 returns HTTP 301 重定向消息,其中一些 html 内容的内容类型为 text/html。默认情况下,WebClient 不遵循 301 重定向,而是尝试将返回的 html 消息解析为假定的 class。这显然失败并产生 UnsupportedMediaTypeException 异常。 这可能会因为 Postman 默认遵循 301 重定向并以完全透明的方式进行而进一步混淆。给人的印象是您通过 http 请求获得了预期的内容。
解决方法:使用https请求。