RestTemplate實現發送帶headers的GET請求
RestTemplate 發送帶headers的GET請求
需求:發送自定義header的GET請求,header中需要插入一個簽名。
發送自定義header的POST請求
之前寫過一個類似的請求,但是是POST的。這個也摸瞭一段時間,自己看參數整瞭出來。代碼如下:
// header填充 LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.put("Content-Type", Collections.singletonList("application/json;charset=UTF-8")); headers.put("signature", Collections.singletonList(makeSignature(form.getNewMobile()))); // body填充 JSONObject json = new JSONObject(); json.put("oldMobile", mobile); json.put("newMobile", form.getNewMobile()); HttpEntity<String> request = new HttpEntity<String>(json.toString(), headers); // 一個單例的restTemplate RestTemplate restTemplate = HttpInvoker.getRestTemplate(); // 發送請求 ResponseEntity<String> response = restTemplate.postForEntity(whiteListURL, request, String.class);
很簡單的想著,隻需要把上面的postForEntity()改成get的就行,但不是這樣的。
發送自定義header的GET請求
Update: 2019/12/11
從鏈接學到瞭一種比較友好的寫法:
private static void getEmployees(){ final String uri = "http://localhost:8080/springrestexample/employees"; RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class); System.out.println(result); }
粗略看瞭看postForEntity()和getForEntity()這兩個方法的實現,都是準備參數,然後調用execute()方法,如下:
// POST @Override public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException { RequestCallback requestCallback = httpEntityCallback(request, responseType); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType); return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables)); } // GET @Override @Nullable public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException { RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); }
區別就在於RequestCallback實例化的時候,傳的參數不一樣。POST的時候,是將header做為參數傳給瞭RequestCallback。再然後就是execute()中的GET和POST參數不一樣。到這個時候,發送自定義header的GET請求,已經很明顯瞭。
實例化的函數,都是public的。
如果不是public的,或者說我們不能直接訪問到,還可以考慮通過反射的方式去調用相關的方法,但這裡不需要用反射瞭。
結果
// header填充 LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.put("Content-Type", Collections.singletonList("application/json;charset=UTF-8")); headers.put("signature", Collections.singletonList(makeSignature(mobile))); // 獲取單例RestTemplate RestTemplate restTemplate = HttpInvoker.getRestTemplate(); HttpEntity request = new HttpEntity(headers); // 構造execute()執行所需要的參數。 RequestCallback requestCallback = restTemplate.httpEntityCallback(request, JSONObject.class); ResponseExtractor<ResponseEntity<JSONObject>> responseExtractor = restTemplate.responseEntityExtractor(JSONObject.class); // 執行execute(),發送請求 ResponseEntity<JSONObject> response = restTemplate.execute(apiAddress + "/xxx/whitelist/check?phone=" + mobile, HttpMethod.GET, requestCallback, responseExtractor);
雖然很簡單,但是看似不可能,自己卻做到瞭、完成瞭,就很有成就感。
RestTemplate優雅的發送Get請求
在我們的項目中,如果借助RestTemplate發送帶參數的Get請求,我們可以通過拼接字符串的方式將url拼接出來,比如下面這種方式:
String url = "http://127.0.0.1:8080/rest/get?name="+ name +"&id=" + id; ResponseEntity<RestVO> forEntity = restTemplate.getForEntity(url, RestVO.class);
然而這種方式不太優雅,我們還可以通過以下幾種方式發送Get請求
方式1:使用占位符
String url = "http://127.0.0.1:8080/rest/path/{name}/{id}"; Map<String, Object> params = new HashMap<>(); params.put("name", "這是name"); params.put("id", 1L); ResponseEntity<RestVO> forEntity = restTemplate.getForEntity(url, RestVO.class, params);
Map的key要和url中的占位符一致
方式2:使用LinkedMultiValueMap和UriComponentsBuilder
String url = "http://127.0.0.1:8080/rest/get"; MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("name", "這是name"); params.add("id", "1"); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); URI uri = builder.queryParams(params).build().encode().toUri(); ResponseEntity<RestVO> forEntity = restTemplate.getForEntity(uri, RestVO.class); return forEntity.getBody();
方式2看起來是最優雅的,將參數的設置和url分離。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- java實用型-高並發下RestTemplate的正確使用說明
- 使用SpringBoot跨系統調用接口的方案
- java分佈式基於RestTemplate的使用方法
- spring boot RestTemplate 發送get請求的踩坑及解決
- RestTemplate接口調用神器常見用法匯總