Spring RestTemplate带Header调用接口返回乱码,求解决方案
解决RestTemplate exchange方法返回乱码(getForObject正常)的问题
我碰到过几乎一模一样的情况,你的问题大概率不是单纯的UTF-8编码问题,而是服务端返回了压缩后的响应,但你的RestTemplate没配置解压处理!
为什么会出现这种差异?
你用getForObject能拿到正常结果,是因为RestTemplate的默认请求逻辑会自动添加Accept-Encoding请求头,服务端收到后返回未压缩的明文;而你自定义请求头时漏掉了这个字段,服务端直接返回了gzip/deflate格式的二进制压缩数据,StringHttpMessageConverter把二进制字节当成普通字符串解析,自然就变成一堆乱码了。
先做个简单验证
调用接口后,打印或查看响应的Content-Encoding头字段,如果值是gzip或者deflate,那就100%确认是压缩的问题。
两种可行解决方案
方式一:用HttpClient请求工厂(推荐)
HttpClient会自动处理压缩响应,不需要手动写解压逻辑,步骤很简单:
- 先引入HttpClient依赖(Maven示例):
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> <!-- 替换成最新稳定版即可 --> </dependency>
- 配置RestTemplate并修改请求头:
// 创建HttpClient请求工厂 HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); RestTemplate restTemplate = new RestTemplate(requestFactory); // 更新你的请求头方法,添加支持压缩的字段 private MultiValueMap<String, String> getHeadersInfo(HttpServletRequest request) { MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.put("Accept", Arrays.asList("text/plain, application/json, application/*+json, */*")); map.put("Content-Type", Arrays.asList("application/json; charset=UTF-8")); // 关键:告诉服务端你支持压缩响应 map.put("Accept-Encoding", Arrays.asList("gzip, deflate")); return map; } // 正常调用exchange方法即可 HttpEntity<String> entity = new HttpEntity<>(body, getHeadersInfo(request)); ResponseEntity<String> responseEntity = restTemplate.exchange(uri, request.getMethod(), entity, String.class);
方式二:手动添加Gzip消息转换器
如果不想引入额外依赖,可以给RestTemplate添加GzipHttpMessageConverter来处理解压:
RestTemplate restTemplate1 = new RestTemplate(); // 先添加Gzip转换器,确保它优先处理解压操作 restTemplate1.getMessageConverters().add(0, new GzipHttpMessageConverter()); // 再添加UTF-8的字符串转换器 restTemplate1.getMessageConverters().add(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); // 同样要在请求头里加上Accept-Encoding MultiValueMap<String, String> headers = getHeadersInfo(request); headers.put("Accept-Encoding", Arrays.asList("gzip, deflate")); HttpEntity<String> entity = new HttpEntity<>(body, headers); ResponseEntity<String> responseEntity = restTemplate1.exchange(uri, request.getMethod(), entity, String.class);
额外提醒
- 别重复添加相同类型的消息转换器,容易导致逻辑冲突;
- 如果服务端强制返回压缩内容(不管你有没有加
Accept-Encoding),那必须配置解压逻辑; - 可以通过
responseEntity.getHeaders()打印响应头,辅助排查问题。
内容的提问来源于stack exchange,提问作者Popeye
相关产品推荐
相关产品推荐

