在RestTemplate中使用HttpComponentsClientHttpRequest解析gzip编码
Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
今天在使用RestTemplate调用接口时发现无法对Gzip的数据进行解压,然后找到了这篇文章: 让RestTemplate使用和解析gzip编码。
原因
文章提到RestTemplate默认不使用Gzip,也不解析 Gzip编码结果,这是因为RestTemplate默认SimpleBufferingClientHttpRequest类。通过idea可以看到RestTemplate的继承关系
在HttpAccessor类中,ClientHttpRequestFactory这个private属性的默认值为一个SimpleClientHttpRequestFactory对象
RestTemplate在获取数据时getForObject、getForEntity、postForObject、postForEntity、exchange等方法最终都是调用execute方法
而execute方法会调用doExecute方法,在doExecute方法中我们可以看到这一句
createRequest方法属于HttpAccessor类,这个方法会通过调用getRequestFactory方法获得requestFactory属性,然后调用requestFactory属性的createRequest方法创建一个实现了ClientHttpRequest接口的对象。
通过RestTemplate类的空参构造函数得到的RestTemplate中requestFactory属性为SimpleClientHttpRequestFactory,因此创建一个SimpleBufferingClientHttpRequest对象,而这个对象是不满足我们自动解析Gzip的要求的,这就是出现问题的原因
解决
RestTemplate类提供了另外一个构造函数,指定一个实现了ClientHttpRequestFactory的对象就能够将其注入到HttpAccessor父类的requestFactory属性中
ClientHttpRequestFactory的实现类关系如图:
HttpComponentsClientHttpRequestFactory能够创建HttpComponentsClientHttpRequest对象,而这个对象能够满足我们的需求
要使用这个需要在项目中添加额外的依赖,以gradle为例:
1 | implementation 'org.apache.httpcomponents:httpclient:4.5.13' |
添加完依赖之后只需要将HttpComponentsClientHttpRequestFactory注入到RestTemplate对象即可
1 |
|
运行之后可以看到自动解析了Gzip的数据