spring restTemplate亂碼問題解決

對於亂碼問題網上也是很多方案,有的是直接把返回的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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章