使用RestTemplate发送POST请求时遇HttpMessageConverter适配异常咨询
no suitable HttpMessageConverter异常的问题 嘿,我看你用RestTemplate发请求的时候踩了no suitable HttpMessageConverter的坑,先帮你拆解下问题,再给你几个可行的解决办法。
你的问题场景
你写的请求代码大概是这样的(注意里面有明显的拼写错误):
HttpHeaders reqheaders= new HttpHeaders(); reqheaders.set(HttpHeaders.Accept,MediaType.Application_xml); reqheaders.set(HttpHeaders.Content_type,MediaType.Application Json); HttpEntity XML= new HttpEntity (json,reqheaders); ResponseEntity<Map> xmlfile= restTemplate.exchange(url,HttpMethod.POST,XML, Map.class);
抛出的报错是:
no suitable HttpMessageConverter found for response type[interface java.util.Map] and content type [application/xml;charset=UTF-8]
问题根源分析
常量拼写错误:首先你代码里的MediaType和HttpHeaders常量全写错了!Java里的常量都是大写命名的,比如
MediaType.Application_xml应该是MediaType.APPLICATION_XML,HttpHeaders.Content_type要写成HttpHeaders.CONTENT_TYPE,MediaType.Application Json这种带空格的写法更是完全错误,应该是MediaType.APPLICATION_JSON。这部分错误会导致请求头设置异常,不过不是核心报错原因。转换器不匹配:核心问题是RestTemplate默认的HttpMessageConverter列表里,没有能把
application/xml格式的响应直接转换成Map类型的转换器。默认的XML转换器(比如Jaxb2RootElementHttpMessageConverter)只能把XML转换成对应注解的实体类,而支持Map转换的转换器大多只处理JSON格式。
可行的解决方案
方案1:修正常量拼写 + 添加Jackson XML转换器(推荐)
这个方案既能解决常量错误,又能让RestTemplate支持XML转Map,步骤如下:
第一步:引入Jackson XML依赖
如果是Maven项目,在pom.xml里加这个依赖:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
第二步:配置RestTemplate添加转换器
给你的RestTemplate实例添加MappingJackson2XmlHttpMessageConverter,它可以完美支持XML和Map的互转:
// 初始化RestTemplate并添加XML转换器 RestTemplate restTemplate = new RestTemplate(); MappingJackson2XmlHttpMessageConverter xmlConverter = new MappingJackson2XmlHttpMessageConverter(); xmlConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML)); restTemplate.getMessageConverters().add(xmlConverter); // 修正后的请求代码 HttpHeaders reqHeaders = new HttpHeaders(); // 用正确的常量设置请求头 reqHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE); reqHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); // 建议指定HttpEntity的泛型类型,避免类型转换问题 HttpEntity<String> requestEntity = new HttpEntity<>(json, reqHeaders); // 现在可以正常接收XML转成的Map了 ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
方案2:用String接收后自行解析
如果不想引入新依赖或者修改RestTemplate配置,可以先把响应以String类型接收,再自己用XML解析工具(比如Dom4j、XStream)把XML字符串转成Map:
// 先修正请求头的常量错误 HttpHeaders reqHeaders = new HttpHeaders(); reqHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE); reqHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); HttpEntity<String> requestEntity = new HttpEntity<>(json, reqHeaders); // 以String类型接收响应 ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); String xmlStr = response.getBody(); // 这里自行编写XML转Map的逻辑,示例用Dom4j(需要引入Dom4j依赖) // 比如: // Map<String, Object> resultMap = XmlUtils.xmlToMap(xmlStr);
方案3:用实体类接收响应(更规范)
如果接口返回的XML结构是固定的,最规范的方式是定义对应的实体类,用JAXB注解标注字段,这样可以用RestTemplate默认的XML转换器直接转换,比转Map更安全:
// 定义对应XML结构的实体类 @XmlRootElement(name = "response") public class XmlResponse { @XmlElement(name = "code") private Integer code; @XmlElement(name = "data") private Map<String, Object> data; // 别忘了加getter和setter方法 } // 请求代码 ResponseEntity<XmlResponse> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, XmlResponse.class);
内容的提问来源于stack exchange,提问作者user9193396

