對於亂碼問題網上也是很多方案,有的是直接把返回的string進行轉碼,不過這樣子不具備通用性,比較麻煩,治標不治本,對於另外一種方式其實就是修改restTemplate的bean裏面的convertor轉換器
通常在引入bean的時候會有如下代碼:
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate=new RestTemplate(factory);
return restTemplate;
}
通過以上代碼可以獲取到restTemplate的實例,通過斷點debug發現以String格式接收數據時,底層採用的是StringHttpMessageConverter來處理請求。查看RestTemplate的構造方法如下:
public RestTemplate() {
this.messageConverters = new ArrayList();
this.errorHandler = new DefaultResponseErrorHandler();
this.uriTemplateHandler = new DefaultUriBuilderFactory();
this.headersExtractor = new RestTemplate.HeadersExtractor();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter(false));
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
} else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
} else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
} else if (jsonbPresent) {
this.messageConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2SmilePresent) {
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
}
if (jackson2CborPresent) {
this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
}
}
通過以上代碼可以發現對於不同response類型的內容處理器是不一樣的
而其中的StringHttpMessageConverter構造方法使用了默認字符集:ISO-8859-1 所以在面對響應格式爲string的內容時就會出現亂碼的情況,而在大部分通過json格式交互的系統中並不會出現此問題
,爲了制定編碼格式爲UTF-8 ,網上存在一種方式是在RestTemplate的構造函數中,對messageConverters賦值時,在下標爲1的位置設置的是StringHttpMessageConverter對象,如下:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
但是這種寫死下標的方式是極爲不推薦的,因爲不排除Spring在後續版本中因爲引入了其他轉換器而導致下標變化的問題。推薦使用以下方式。
所以本人推薦以下用法:
public static void setRestTemplateEncode(RestTemplate restTemplate) {
if (null == restTemplate || ObjectUtils.isEmpty(restTemplate.getMessageConverters())) {
return;
}
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for (int i = 0; i < messageConverters.size(); i++) {
HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
}
}
通過新增的方法,將RestTemplate對象傳遞進去,內部遍歷messageConverters,找到StringHttpMessageConverter並替換爲UTF-8格式的StringHttpMessageConverter對象即可。
此方法在restTemplate構造的時候執行就好了,如下:
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate=new RestTemplate(factory);
setRestTemplateEncode(restTemplate);
return restTemplate;
}