HttpRequestExecutingMessageHandler请求头问题及RestTemplate默认配置咨询
accept-encoding:gzip的问题解析 我来帮你拆解这个问题背后的原因、差异点以及可行的解决方案:
一、默认带accept-encoding:gzip的核心原因
Spring的RestTemplate(包括它底层依赖的HTTP客户端,比如Apache HttpClient)默认会开启内容压缩优化——这个请求头是客户端主动告诉服务端:“我支持gzip压缩的响应,你可以给我传压缩后的内容”。
这么做的目的很直接:压缩后的响应体积更小,能大幅减少网络传输的数据量,提升请求的响应速度。这个行为是由RestTemplate的默认配置触发的:要么是消息转换器(比如MappingJackson2HttpMessageConverter)的自动设置,要么是底层HTTP客户端的拦截器(比如ContentEncodingHttpClientInterceptor)自动添加了这个头。
二、为什么内部测试正常,对接外部服务就报错?
内部的Integration实例之间通信没问题,大概率是因为:
- 内部服务本身支持gzip压缩,而且能和客户端配合默契——服务端返回压缩响应后,客户端会自动解压缩,再把明文内容交给消息转换器处理,自然不会出异常。
而对接外部服务时出问题,通常是两种情况:
- 外部服务返回了gzip压缩的响应,但你的客户端没配置对应的解压缩逻辑,导致消息转换器拿到的是二进制压缩数据,根本没法解析成
MyClass对象,直接抛出转换异常。 - 外部服务不支持gzip压缩,但又没正确处理
accept-encoding头——比如返回了非压缩内容,但响应头却标记了gzip,导致客户端的解压缩逻辑直接报错。
三、为什么自定义RestTemplate后这个头还在?
哪怕你自己实例化了RestTemplate,如果没刻意修改压缩相关的配置,底层HTTP客户端的默认逻辑依然会生效。比如用Apache HttpClient的话,ContentEncodingHttpClientInterceptor这个拦截器是默认注册的,它会自动给请求加上accept-encoding:gzip头。仅仅新建RestTemplate对象,并不会移除这些默认的拦截器或配置。
四、已验证的解决方案和替代思路
你现在用headerFilter("accept-encoding")的方式完全可行,相当于在Spring Integration的消息流里直接把这个头删掉,从根源上避免触发服务端的压缩逻辑。除此之外,还有两种可选方案:
方案1:让RestTemplate自动处理解压缩
如果你想保留压缩优化的好处,可以给RestTemplate配置支持自动解压缩的客户端工厂:
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); CloseableHttpClient httpClient = HttpClientBuilder.create() .addInterceptorFirst(new ContentEncodingInterceptor()) .build(); factory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(factory);
这样客户端收到gzip响应后会自动解压缩,消息转换器就能正常解析内容了。
方案2:移除RestTemplate的默认压缩拦截器
直接把负责添加accept-encoding头的拦截器删掉:
RestTemplate restTemplate = new RestTemplate(); restTemplate.getInterceptors().removeIf(interceptor -> interceptor instanceof ContentEncodingHttpClientInterceptor);
内容的提问来源于stack exchange,提问作者Jose Carlos Canova

