RestTemplate 查詢參數有特殊字符

前面說到如何使用 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);
相關文章
相關標籤/搜索