对于乱码问题网上也是很多方案,有的是直接把返回的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;
}