Spring Boot 3中WebClient处理application/xml遇类型不支持异常
Spring Boot 3.x WebClient处理application/xml报UnsupportedMediaTypeException问题解决
问题背景
从Spring Boot 2.7.2升级到3.x版本后,通过@Configuration配置的WebClient调用XML接口时抛出UnsupportedMediaTypeException,提示Content type 'application/xml' not supported for bodyType=com.package.ResponseObject。已引入以下JAXB依赖:
- jaxb-core - 2.2.11
- jaxb-impl - 2.2.11
- jaxb-runtime - 2.3.6
- jaxb-api - 2.3.1
WebClient配置代码:
public WebClient getWebClient(String url) { WebClient webClient = null; try { webClient = WebClient.builder().baseUrl(url) .defaultHeaders(headers -> { headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE); headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE); headers.setBasicAuth(username, password); }) .exchangeStrategies( ExchangeStrategies.builder() .codecs( configurer -> configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder()) ) .build() ) .build(); } catch (Exception e) { e.printStackTrace(); } return webClient; }
调用代码:
public ResponseObject getResponse(RequestObject request, String clientUrl) throws Exception { ResponseObject result = null; try { WebClient client = getWebClient(clientUrl); BodyInserter<RequestObject, ReactiveHttpOutputMessage> inserter = BodyInserters.fromValue(request); result = client.post().body(inserter).retrieve().bodyToMono(ResponseObject.class).block(); } catch (Exception ex) { throw ex; } return result; }
错误日志:
2023-06-18 17:09:54.875| WARN|r.n.h.c.HttpClientConnect|[d243e7af-1, L:/R:xx.xx.xx.com] The connection observed an error org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.package.ResponseObject at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:392) ~[spring-webflux-6.0.9.jar:6.0.9] at org.springframework.web.reactive.function.BodyInserters.writeWithMessageWriters(BodyInserters.java:382) ~[spring-webflux-6.0.9.jar:6.0.9] at org.springframework.web.reactive.function.BodyInserters.lambda$fromValue$1(BodyInserters.java:98) ~[spring-webflux-6.0.9.jar:6.0.9] at org.springframework.web.reactive.function.client.DefaultClientRequestBuilder$BodyInserterRequest.writeTo(DefaultClientRequestBuilder.java:272) ~[spring-webflux-6.0.9.jar:6.0.9]
原因分析
- 依赖不兼容:Spring Boot 3.x基于Jakarta EE 9+,所有
javax.*包已替换为jakarta.*,当前引入的是旧的javax版本JAXB依赖,无法与Spring Boot 3的Jakarta生态兼容。 - 缺少XML编码器配置:当前WebClient仅配置了
Jaxb2XmlDecoder(用于解析响应XML),但请求时需要Jaxb2XmlEncoder来序列化请求体为XML,未配置编码器导致请求阶段无法处理application/xml类型。
解决方案
1. 替换为Jakarta版本的JAXB依赖
移除所有旧的javax JAXB依赖,添加Jakarta版本的依赖(以Maven为例):
<dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <scope>runtime</scope> </dependency>
注:Spring Boot 3.x的bom会管理这些依赖的版本,无需手动指定版本号。
2. 同时配置Jaxb2XmlDecoder和Jaxb2XmlEncoder
修改WebClient配置,在ExchangeStrategies中同时添加编码器和解码器:
public WebClient getWebClient(String url) { try { return WebClient.builder().baseUrl(url) .defaultHeaders(headers -> { headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE); headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE); headers.setBasicAuth(username, password); }) .exchangeStrategies(ExchangeStrategies.builder() .codecs(configurer -> { DefaultCodecs defaultCodecs = configurer.defaultCodecs(); defaultCodecs.jaxb2Decoder(new Jaxb2XmlDecoder()); defaultCodecs.jaxb2Encoder(new Jaxb2XmlEncoder()); }) .build()) .build(); } catch (Exception e) { e.printStackTrace(); return null; } }
3. 更新实体类的JAXB注解
将实体类(RequestObject、ResponseObject)中原来的javax.xml.bind.*注解替换为jakarta.xml.bind.*,例如:
- 替换
@javax.xml.bind.annotation.XmlRootElement为@jakarta.xml.bind.annotation.XmlRootElement - 替换
@javax.xml.bind.annotation.XmlElement为@jakarta.xml.bind.annotation.XmlElement - 其他JAXB注解同理更新
验证
修改完成后重新启动服务,调用接口即可正常处理application/xml类型的请求和响应。
内容的提问来源于stack exchange,提问作者user3312160
相关产品推荐
相关产品推荐

