Spring中RestTemplate的使用方法
一、REST
在網際網路中,我們會通過請求url來對網路上的資源做增刪改查等動作,這裡的請求包含兩部分:
動詞,主要包括增、刪、改、查
名詞,就是網路中的各種資源
傳統的非REST風格的請求方式是把動詞和名詞全都放在url中。
例如,對裝置的操作可能是這樣的:
新增裝置:http://test/device/add
刪除裝置:http://test/device/delete
修改裝置:http://test/device/modify
查詢裝置:http://test/device/find
這樣就存在一個規範的問題,例如,新增裝置這個動作的單詞應該是用add還是create?http方法是用GET還是用POST?等等
REST風格的請求方式是用http請求方法表示增刪改查動作,而url中只保留名詞,也就是對資源位置的描述,這樣就避免了動作描述規範的問題。
還是以對裝置的操作舉例,REST風格的請求是這樣的:
新增裝置:http://test/device 請求方法是POST
刪除裝置:http://test/device 請求方法是DELETE
修改裝置:http://test/device 請求方法是PUT
查詢裝置:http://test/device/:id 請求方法是GET
二、Spring中對REST請求的處理
Spring中可以使用RestTemplate來操作REST資源,主要包含以下幾個方法:
getForEntity(),getForObject(),傳送HTTP GET請求,getForEntity()返回的是ResponseEntity物件,裡面包含響應實體物件及響應狀態碼,而getForObject()則直接返回響應實體物件
postForEntity(),postForObject(),傳送HTTP POST請求,postForEntity()返回的是ResponseEntity物件,裡面包含響應實體物件及響應狀態碼,而postForObject()則直接返回響應實體物件
put(),傳送HTTP PUT請求
delete(),傳送HTTP DELETE請求
exchange(),可以傳送GET、POST、PUT和DELETE中的任意一種請求,同時還可以自定義請求頭
下面舉例說明幾種方法的用法
首先建立一個實體類Device,後面的方法會用到這個實體類
public class Device { private String ip; private String mac; }
建立一個用於測試的Controller類
@RestController @RequestMapping(value = "/consumer") public class ConsumerController { private RestTemplate restTemplate = new RestTemplate(); private String urlPrefix = "http://localhost:8080/test/producer"; // ... }
1. GET請求
GET請求有兩組過載方法:
1.1 getForEntity()
這個方法有多個過載方法
方法一:
getForEntity(String url, Class<T> responseType, Object... uriVariables)
其中,url就是請求的url,responseType是返回的實體類型別,uriVariables是uri或請求引數
程式碼示例如下:
@RequestMapping(value = "/get1") public String testGetForEntity1() { String url = urlPrefix + "/get"; ResponseEntity<Device> response = restTemplate.getForEntity(url, Device.class); System.out.println("Device: " + response.getBody() + ", code: " + response.getStatusCodeValue()); return response.getBody().toString(); }
返回的response中既包含返回的實體物件(通過response.getBody()獲取),又包含返回狀態碼(通過response.getStatusCodeValue()獲取)
這裡的url中沒有任何引數,所以uriVariables為空。如果url中需要傳一些引數,可以通過以下方式傳遞:
@RequestMapping(value = "/get2") public String testGetForEntity3() { String url = urlPrefix + "/get?protocol={protocol}&operator={operator}"; ResponseEntity<Device> response = restTemplate.getForEntity(url, Device.class, "NBIot", "ChinaMobile"); System.out.println("Device: " + response.getBody() + ", code: " + response.getStatusCodeValue()); return response.getBody().toString(); }
這裡傳了兩個引數protocol和operator
方法二:
getForEntity(String url, Class<T> responseType, Map<String,?> uriVariables)
這種方法是將uriVariables用Map方式傳入,如果引數比較多的話,這種方式方便方法之間的引數傳遞
程式碼示例如下:
@RequestMapping(value = "/get3") public String testGetForEntity2() { Map<String, String> classifyMap = new HashMap<>(); classifyMap.put("protocol", "NBIot"); classifyMap.put("operator", "ChinaMobile"); String url = urlPrefix + "/get?protocol={protocol}&operator={operator}"; ResponseEntity<Device> response = restTemplate.getForEntity(url, Device.class, classifyMap); System.out.println("Device: " + response.getBody() + ", code: " + response.getStatusCodeValue()); return response.getBody().toString(); }
方法三:
getForEntity(URI url, Class<T> responseType)
這種方法是把String型別的url替換成java.net.URI型別的url
2.2 getForObject()
這個方法和getForEntity()的3個過載方法請求引數是完全一樣的,不同的是getForObject()直接返回的是實體物件,而沒有返回狀態碼。如果不關注狀態碼,只關注返回內容,可以使用這個方法。
方法一:
getForObject(String url, Class<T> responseType, Object... uriVariables)
程式碼示例如下:
不包含請求引數的方法:
@RequestMapping(value = "/get4") public String testGetForObject1() { String url = urlPrefix + "/get"; Device device = restTemplate.getForObject(url, Device.class); System.out.println("Device: " + device); return device.toString(); }
包含請求引數的方法:
@RequestMapping(value = "/get5") public String testGetForObject2() { String url = urlPrefix + "/get?protocol={protocol}&operator={operator}"; Device device = restTemplate.getForObject(url, Device.class, "NBIot", "ChinaMobile"); System.out.println("Device: " + device); return device.toString(); }
方法二:
getForObject(String url, Class<T> responseType, Map<String,?> uriVariables)
程式碼示例如下:
@RequestMapping(value = "/get6") public String testGetForObject3() { Map<String, String> classifyMap = new HashMap<>(); classifyMap.put("protocol", "NBIot"); classifyMap.put("operator", "ChinaMobile"); String url = urlPrefix + "/get?protocol={protocol}&operator={operator}"; Device device = restTemplate.getForObject(url, Device.class, classifyMap); System.out.println("Device: " + device); return device.toString(); }
方法三:
getForObject(URI url, Class<T> responseType)