RestTemplate--解決中文亂碼
阿新 • • 發佈:2019-02-19
utf-8 orm ping list tde 字符 替換 形式 add
在開發扇貝-每日一句時,使用RestTemplate請求扇貝接口,並保存返回的數據。原本正常的代碼,經過架構升級後,請求接口時,會返回亂碼數據。經過直接訪問接口等形式,最終確認是RestTemplate這個bean有問題。
對RestTemplate的聲明也比較簡單,通過對apache的httpclient進行封裝,返回bean實例。代碼如下:
@Bean
RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
通過斷點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()); } }
其中的StringHttpMessageConverter構造方法使用了默認字符集:ISO-8859-1。
public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> { public static final Charset DEFAULT_CHARSET; …… public StringHttpMessageConverter() { this(DEFAULT_CHARSET); } …… static { DEFAULT_CHARSET = StandardCharsets.ISO_8859_1; } }
private final List<HttpMessageConverter<?>> messageConverters
根據RestTemplate的構造方法的源碼得知所有的HttpMessageConverter都是放在final List<HttpMessageConverter<?>> messageConverters這個常量集合中。雖然集合不可修改,但是可以對其中的元素StringHttpMessageConverter進行修改。
解決方案思路都是將ISO-8859-1的StringHttpMessageConverter替換為UTF-8的StringHttpMessageConverter。
- 示例代碼一
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
- 示例代碼二
for (HttpMessageConverter<?> httpMessageConverter : restTemplate.getMessageConverters()) {
if (httpMessageConverter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
}
}
- 示例代碼三
// stream .findFirst(); 也是可以的
Optional<HttpMessageConverter<?>> converter = restTemplate.getMessageConverters().stream().filter(c -> c instanceof StringHttpMessageConverter).findAny();
if(converter.isPresent()) {
((StringHttpMessageConverter) converter.get()).setDefaultCharset(Charset.forName("UTF-8"));
}
RestTemplate--解決中文亂碼