SpringBoot中POST请求Postman正常但RestTemplate响应异常
SpringBoot RestTemplate POST请求响应乱码问题排查与修复
注:问题参考截图:
相关原始代码:
String xml = jaxbObjectToXML(createSRINTOSSet); RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); // create headers headers.add("MAXAUTH", auth); headers.setContentType(MediaType.TEXT_PLAIN); try { HttpEntity<String> request = new HttpEntity<String>(xml, headers); response = restTemplate.postForEntity(maximoIntegrationURI, request, String.class);
为什么Postman调用正常,RestTemplate返回异常
Postman内置了多项适配逻辑用于兼容不同服务端配置:
- 默认携带
Accept-Encoding: gzip, deflate, br请求头,收到压缩响应会自动解压 - 自动识别响应内容编码,即使响应头未正确声明charset也会尝试用通用编码解析
- 默认携带
Accept: */*请求头,告知服务端可接收任意格式响应
RestTemplate默认无上述兜底适配逻辑,严格按照配置执行,服务端配置发生变更后就会出现异常。
可能的成因
- 服务端新增响应压缩配置:之前未开启gzip/deflate压缩时返回纯文本XML,开启后RestTemplate默认不会自动解压,拿到的压缩二进制流转为String后就会显示为乱码或类似加密的内容。
- 响应编码不匹配:服务端当前返回的响应头未声明charset,或声明的编码与实际内容编码不一致,RestTemplate默认使用
ISO-8859-1解析String类型响应,遇到中文或特殊字符就会乱码。 - 请求缺少Accept头:代码中未设置Accept请求头,若服务端近期修改了内容协商规则,未匹配到Accept头时就会返回非XML格式的内容,Postman因为默认携带
Accept: */*可正常拿到XML响应。 - String消息转换器默认编码问题:RestTemplate内置的
StringHttpMessageConverter默认编码为ISO-8859-1,如果响应内容是UTF-8编码的XML就会出现乱码。
修复方案
1. 配置RestTemplate支持gzip自动解压
引入Apache HttpComponents依赖,替换默认请求工厂开启自动解压:
// 构造支持自动解压的请求工厂 HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory( HttpClientBuilder.create() .disableCookieManagement() .build() ); RestTemplate restTemplate = new RestTemplate(factory);
2. 新增Accept头指定接收格式
在请求头中添加XML格式接收声明:
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
3. 替换String消息转换器编码为UTF-8
修改RestTemplate的消息转换器配置,使用UTF-8编码解析字符串响应:
RestTemplate restTemplate = new RestTemplate(); // 移除默认的ISO-8859-1编码String转换器 restTemplate.getMessageConverters().removeIf(converter -> converter instanceof StringHttpMessageConverter); // 新增UTF-8编码的String转换器 restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
4. 打印响应头快速定位
打印RestTemplate返回的完整响应头,确认Content-Encoding、Content-Type字段的值即可快速定位问题:
HttpHeaders responseHeaders = response.getHeaders(); System.out.println(responseHeaders);
内容的提问来源于stack exchange,提问作者Sathiyamoorthi G
相关产品推荐
相关产品推荐

