前面說到如何使用 Spring 的 RestTemplate 進行數據請求,如何避免亂碼問題,在項目開發中還遇到了文件上傳和下載,因此也寫了使用 RestTemplate 包裝文件下載的組件。一樣,項目越大遇到的問題就會越多,當使用 GET 請求時,若是URL中的參數有特殊字符,好比 '#' ,就會致使查詢錯誤。java
一、RestTemplate 下載組件網絡
http://my.oschina.net/heweipo/blog/683233app
二、RestTemplate 亂碼解決ide
http://my.oschina.net/heweipo/blog/611514ui
重現步驟,以下代碼 編碼
public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); String url = "http://localhost:8180/workbench/questionBank/paper?search=#&query=123"; HttpEntity<?> entity = new HttpEntity<>(headers); HttpEntity<String> response = restTemplate.exchange(url,HttpMethod.GET,entity,String.class); System.out.println(response.getBody()); }
原本請求中是有參數 search 和 query ,就由於 search 中使用了特殊字符 # , 然而在服務端獲取參數時獲得的參數只有 search = ;url
調試結果:.net
問題出現的緣由,查看 RestTemplate 的以下代碼 調試
@Override public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor, Object... urlVariables) throws RestClientException { // 這裏進行網絡轉碼,由於咱們傳遞的URL是字符串,最後都要統一轉爲URL,並且對於字符都應該進行網絡編碼, // 問題就出如今這裏,咱們若是本身手動把參數進行網絡編碼,那麼問題就不會出現 URI expanded = getUriTemplateHandler().expand(url, urlVariables); return doExecute(expanded, method, requestCallback, responseExtractor); }
修改後的代碼 rest
public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); String url = "http://localhost:8180/workbench/questionBank/paper?search=#&query=123"; UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); URI uri = builder.build().encode().toUri(); HttpEntity<?> entity = new HttpEntity<>(headers); HttpEntity<String> response = restTemplate.exchange( uri, HttpMethod.GET, entity, String.class); System.out.println(response.getBody()); }
調試結果
總結:
網絡傳輸須要進行網絡編碼,網絡編碼可使用以下API
HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url) .queryParam("msisdn", msisdn) .queryParam("email", email) .queryParam("clientVersion", clientVersion) .queryParam("clientType", clientType) .queryParam("issuerName", issuerName) .queryParam("applicationName", applicationName); HttpEntity<?> entity = new HttpEntity<>(headers); HttpEntity<String> response = restTemplate.exchange( builder.build().encode().toUri(), HttpMethod.GET, entity, String.class);