RestTemplate中文亂碼Response問號
背景描述
需要請求內(nèi)部restful接口路狮,那么有以下兩種方式可以選擇
- httpclient封裝請求
- 優(yōu)點(diǎn) 最底層的實(shí)現(xiàn)方式,很直觀的能看到整個(gè)過程是如何實(shí)現(xiàn)的,也方便調(diào)優(yōu)耗拓,調(diào)參數(shù)等等操作簡單明了揣苏。
- 缺點(diǎn) 代碼繁瑣涮因,大段大段的實(shí)現(xiàn),而且互相之間封裝的方式又千奇百怪施符。
- RestTemplate調(diào)用接口
- 優(yōu)點(diǎn) 經(jīng)過模板模式封裝以后提供了簡潔明了的設(shè)計(jì)和通用的模板方法進(jìn)行調(diào)用,基本可以滿足絕大多數(shù)要求擂找,代碼優(yōu)美明了操刀,耦合度大幅度降低。
- 缺點(diǎn) 學(xué)習(xí)成本相對方式一較大婴洼,封裝程度高難以調(diào)試和發(fā)現(xiàn)問題骨坑,容易擴(kuò)展但是需要很了解整個(gè)包如何使用。
問題現(xiàn)象
發(fā)送POST請求柬采,參數(shù)有中文有英文欢唾,返回的結(jié)果看起來除了中文亂碼是正常的。其中請求方法使用了模板方法的postForObject
粉捻,直接返回字符串礁遣。中文亂碼表現(xiàn)為???
。
簡單的分析
- 出現(xiàn)問號的亂碼看起來并不是GBK UTF-8這種類型的編碼問題肩刃,否則會出現(xiàn)一堆奇怪的
昆金卡考燙
什么的而不是???
祟霍。 - 請求其他人的接口返回中文正常請求這個(gè)接口返回亂碼杏头,說明可能原因有一部分在接口部分。
谷歌百度了一天沸呐,大部分人都說的是StringHttpMessageConverter
的原因醇王,RestTemplate會我們默認(rèn)注冊一系列Converter,其中包括一個(gè)StringHttpMessageConverter
崭添,詳細(xì)的可以用搜索引擎搜索相關(guān)寓娩。他的默認(rèn)編碼確實(shí)是ISO-8859-1,這是spring-web寫死在代碼中的默認(rèn)值,但是修改了該值并不見效呼渣,返回結(jié)果沒有發(fā)生一點(diǎn)變化棘伴,而且也和分析1中的判斷有出入。翻閱一些人的文章和文檔后發(fā)現(xiàn)屁置,StringHttpMessageConverter
本質(zhì)上是一個(gè)轉(zhuǎn)換請求的處理器焊夸,他是用來解決服務(wù)端接收到中文亂碼現(xiàn)象的解決方式,另外有處理器用來處理返回后的數(shù)據(jù)來轉(zhuǎn)換成文本或者實(shí)體蓝角,比如MappingJackson2HttpMessageConverter
阱穗。RestTemplate提供很多處理器來處理返回文本的不同格式,比如text/html text/json text/plain帅容,正合了上述分析2中的第二點(diǎn)颇象,有的人接口默認(rèn)返回的格式剛好和MappingJackson2HttpMessageConverter
默認(rèn)解析的格式一樣。
解決方式
上代碼
@Configuration
public class BeanConfig {
@Bean(value = "rest")
public RestTemplate getRestTemplateBuilder(){
RestTemplate restTemplate = new RestTemplateBuilder()
.setConnectTimeout(1000)
.setReadTimeout(1000)
.build();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.ALL);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
restTemplate.getMessageConverters().remove(i);
restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
}
if(restTemplate.getMessageConverters().get(i) instanceof MappingJackson2HttpMessageConverter){
try{
((MappingJackson2HttpMessageConverter) restTemplate.getMessageConverters().get(i)).setSupportedMediaTypes(mediaTypeList);
}catch(Exception e){
e.printStackTrace();
}
}
}
return restTemplate;
}
}
重點(diǎn)在于第一個(gè)處理器加上了修改了默認(rèn)編碼并徘,第二個(gè)處理添加了mediaTypeList.add(MediaType.ALL);
解析所有返回?cái)?shù)據(jù)的格式遣钳。
本次的問題有別于網(wǎng)上所有跟這個(gè)問題相關(guān)的答案,但是真的花了我大半天的時(shí)間麦乞。主要還是對RestTemplate不熟悉的緣故蕴茴。