RestTemplate亂碼問題描述
RestTemplate是Spring-web提供的用於訪問Rest服務的客戶端,RestTemplate提供了多種便捷的訪問遠程Http服務的方法,能夠大大提高客戶端的編寫效率。
RestTemplate默認依賴JDK提供http連接的能力(HttpURLConnection),在項目中會通過setRequestFactory方法或構造方法替換爲例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library,其中OkHttp的性能優越,使用較多。
在使用 restTemplate.getForEntity方法抓取網頁內容時發現返回的內容爲亂碼,代碼如下:
package com.pbteach.test
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.*;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class RestTemplateTest {
@Autowired
RestTemplate restTemplate;
//獲取網頁內容
@Test
public void gethtml(){
//要抓取的網頁地址
String url = "http://www.pbteach.com/";
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
String body = forEntity.getBody();
System.out.println(body);
}
}
問題分析
RestTemplate在消息解析過程中有很多的消息轉換器,跟蹤源代碼,如下:
當RestTemplate默認使用String存儲body內容時默認使用ISO_8859_1字符集,如果內容有中文則會亂碼。
問題解決
配置StringHttpMessageConverter 消息轉換器,使用utf-8字符集。
修改RestTemplate的定義方法
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());
//消息轉換器列表
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
//配置消息轉換器StringHttpMessageConverter,並設置utf-8
messageConverters.set(1,
new StringHttpMessageConverter(StandardCharsets.UTF_8));//支持中文字符集,默認ISO-8859-1,支持utf-8
return restTemplate;
}
再次跟蹤源代碼,StringHttpMessageConverter使用的字符集爲utf-8。
重啓應用,抓取網頁內容,不再亂碼了!