转载自:https://blog.csdn.net/zhanshenzhi2008/article/details/79186663
在网上尝试了多种方案,最终这个可以有效解决,为了避免大家走弯路,在此分享下。
前一段时间接触SpringBoot,要搭建访问其他系统的架构,于是用Rest技术访问其他系统。
问题
用String res = restTemplate.postForObject(url, param, String.class获取String类型的时候,发现乱码。
原因
通过源码Debug发现,主要是StringHttpMessageConverter这个类默认类型并不是utf-8,而是ISO-8859-8,所以要解决这个问题,就得修改这个类的字符集。
错误的解决方案
之前看过网上的解决方案:
1. 通过restTemplate.getMessageConverters
方法获取List<HttpMessageConverter<?>>
,
2. 然后循环并将StringHttpMessageConverter
移出掉,然后再循环体外add
一个new
的HttpMessageConverter
类且字符集已设为utf-8
。
以上方案的问题所在
这种方案其实在调用restTemplate.postForObject(url, param, String.class
获取String
类型的时候会报错,因为RestTemplate
会for
循环messageConverters
,依次去处理String
类型的response
,而StringHttpMessageConverter
是属于第二个,最后一个是jackson
转换类,那么add
进去的是最后一个转换类,那么string
类型的过去在jackson
转换类里就会报错,jackson
要求的类型JsonArray
类型的参数。
最终解决方案:
循环体内获取对应的对应的转换类,然后调用自己的setDefaultCharset(StandardCharset.UTF-8)即可。代码如下(以下有些代码是刚刚自己手动敲的,还没有检查语法问题,不过方案在公司已经测试过,不会有问题。):
@Configuration
public class RestConfiguration {
@Bean
@ConditionalOnMissingBean({RestOperations.class, RestTemplate.class})
public RestOperations restOperations() {
// SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// requestFactory.setReadTimeout(5000);
// requestFactory.setConnectTimeout(5000);
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
// 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为 "ISO-8859-1")
****List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter)converter).setDefaultCharset(StandardCharset.UTF_8)
}
}
// 解决text/plain的,比如微信等
restTemplate.getMessageConverter().add(new NewMappingJackJson2HttpMessageConverter())
return restTemplate;
}****
}
/**
* 由于默认构造的MappingJackson2HttpMessageConverter中的supportedMediaTypes只支持:applicantion/json的,所以再添加MediaType.TEXT_PLAIN的MediaType的支持
*/
public static finanl class NewMappingJackson2HttpMessageConverter extends MappingJackon2HttpMessageConverter{
public NewMappingJackson2HttpMessageConverter(){
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.TEXT_PLAIN);
setSupportedMediaTypes(mediaTypes);
}
}