feign版本
feign調(diào)用時報錯:
feign.codec.DecodeException: Error while extracting response for type [class com.uaa.entity.resp.RespCompanyData] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (ByteArrayInputStream); line: 1, column: 2]
解決方案
1:pom文件添加feign-httpclient
,將feign的http組件改為apache httpClient
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2:檢查配置文件是否開啟了feign的gzip壓縮
feign:
compression:
request:
enabled: true
response:
enabled: true
如果找到該配置嚷闭,請設(shè)置為false
排查思路
1.跟蹤拋出異常的堆棧炬太,發(fā)現(xiàn)在對返回結(jié)果的json解析中拋出異常
2.為什么會解析json失敗呢集币,我們單獨調(diào)用feign對應(yīng)的接口是正常的奉瘤,json也是正晨睿可以解析的
3.難道feign的處理過返回的內(nèi)容国裳,又去跟了下fegin處理過程發(fā)現(xiàn)從response獲取到流并沒有任何異常,難道是出在了源頭全跨?但是源頭又沒有任何異常缝左,此時思緒已經(jīng)混亂,試著在google上查找有沒有相關(guān)的問題浓若,沒想到在feign的github上找到類似問題https://github.com/OpenFeign/feign/issues/934
可以看到渺杉,feign默認的Client不支持設(shè)置了Content-Encoding為gzip的處理∨驳觯看到此趕緊去看了下postman的Response Headers,果然發(fā)現(xiàn)了一行Content-Encoding:gzip!!
4.問題已然發(fā)現(xiàn)是越,就是響應(yīng)的內(nèi)容經(jīng)過gzip編碼,feign默認的Client不支持gzip解碼碌上。那么在此跟蹤一下feign的源碼查看處理過程英妓,從入口SynchronousMethodHandler
開始挽放,在122行開始獲取響應(yīng)內(nèi)容
response = logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
最終在Logger
的102行找到響應(yīng)流的讀取,讀取的流程如下:
5.最終問題出在feign使用默認的HttpURLConnection,并沒有經(jīng)過任何處理敷燎,導(dǎo)致讀取的是gzip壓縮后的內(nèi)容暂筝。此時我們可以將其置換為Httpclient,其內(nèi)部ResponseContentEncoding
的process
方法硬贯,取出了Content-Encoding并判斷不為空焕襟,然后獲取對應(yīng)的處理方式。
補充
上面所說feign默認的Client不支持gzip解碼可能容易引起歧義它褪,應(yīng)該是fegin默認的Client對響應(yīng)流不支持對gzip后的字節(jié)流進行解析,所以在序列化成對象時會存在解析問題翘悉。如果一定要接收可以使用ResponseEntity<byte[]>
來接收,這樣feign就不會對其反序列化了茫打。至于feign.compression.request.enabled=true
,feign.compression.response.enabled=true
配置的內(nèi)容在FeignAcceptGzipEncodingInterceptor
,FeignContentGzipEncodingInterceptor
,大致可以看出只是在請求頭添加了Header而已
2020/3/13
spring已添加支持妖混,SpringCloud版升級到Hoxton即可
https://github.com/spring-cloud/spring-cloud-openfeign/pull/230
# 對于OkHttpClient以外的http客戶端老赤,可以啟用默認的gzip解碼器以UTF-8編碼解碼gzip響應(yīng)
feign.compression.response.enabled=true
feign.compression.response.useGzipDecoder=true
2020/12/01
對于仍然存在問題的伙伴,可以直接使用OkHttp設(shè)置為feign的客戶端(因為okhttp是默認支持gzip壓縮)制市,不需要關(guān)注spring cloud版本诗越;最簡單的方案,也是最推薦的方案息堂。
-
application.yml
配置文件添加以下配置
feign:
okhttp:
enabled: true
-
maven
添加依賴
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>