1. 程式人生 > >Spring中RestTemplate的使用方法

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)