轉載自:https://blog.csdn.net/itguangit/article/details/78825505
作為開發人員,我們經常關注於構建偉大的軟件來解決業務問題。數據只是軟件完成工作時
要處理的原材料。但是如果你問一下業務人員,數據和軟件誰更重要的話,他們很可能會選擇
數據。數據是許多業務的生命之血。軟件通常是可以替換的,但是多年積累的數據是永遠不能
替換的。
近幾年來,以信息為中心的表述性狀態轉移(Representational State Transfer,REST)已經稱為替代傳統SOAP Web 服務的流行方案.
SOAP關注的一般是行為和處理,而REST關注的是要處理的數據.
從Spring3.0開始,Spring為創建Rest API提供了良好的支持.
REST提供了一個更簡單的可選方案。另外,很多的現代化應用都會有移動或富JavaScript客戶端,它們都會使用運行在服務器上REST API。
REST的基礎知識
**當談論REST時,有一種常見的錯誤就是將其視為“基於URL的Web服務”——將REST作為另一
種類型的遠程過程調用(remote procedure call,RPC)機制,就像SOAP一樣,只不過是通過簡單
的HTTP URL來觸發,而不是使用SOAP大量的XML命名空間。**
**恰好相反,REST與RPC幾乎沒有任何關系。RPC是面向服務的,並關注於行為和動作;而REST
是面向資源的,強調描述應用程序的事物和名詞**。
更簡潔地講,**REST就是將資源的狀態以最適合客戶端或服務端的形式從服務器端轉移到客戶
端(或者反過來)**。
在REST中,資源通過URL進行識別和定位。至於RESTful URL的結構並沒有嚴格的規則,但是
URL應該能夠識別資源,而不是簡單的發一條命令到服務器上。再次強調,關注的核心是事
物,而不是行為。
Spring 中如何使用Rest資源
借助 RestTemplate,Spring應用能夠方便地使用REST資源
Spring的 RestTemplate訪問使用了模版方法的設計模式.
模版方法將過程中與特定實現相關的部分委托給接口,而這個接口的不同實現定義了接口的不同行為.
RestTemplate定義了36個與REST資源交互的方法,其中的大多數都對應於HTTP的方法。
其實,這里面只有11個獨立的方法,其中有十個有三種重載形式,而第十一個則重載了六次,這樣一共形成了36個方法。
-
delete() 在特定的URL上對資源執行HTTP DELETE操作
-
exchange()
在URL上執行特定的HTTP方法,返回包含對象的ResponseEntity,這個對象是從響應體中
映射得到的 -
execute() 在URL上執行特定的HTTP方法,返回一個從響應體映射得到的對象
-
getForEntity() 發送一個HTTP GET請求,返回的ResponseEntity包含了響應體所映射成的對象
-
getForObject() 發送一個HTTP GET請求,返回的請求體將映射為一個對象
-
postForEntity()
POST 數據到一個URL,返回包含一個對象的ResponseEntity,這個對象是從響應體中映射得
到的 -
postForObject() POST 數據到一個URL,返回根據響應體匹配形成的對象
-
headForHeaders() 發送HTTP HEAD請求,返回包含特定資源URL的HTTP頭
-
optionsForAllow() 發送HTTP OPTIONS請求,返回對特定URL的Allow頭信息
-
postForLocation() POST 數據到一個URL,返回新創建資源的URL
-
put() PUT 資源到特定的URL
實際上,由於Post 操作的非冪等性,它幾乎可以代替其他的CRUD操作.
Get請求
RestTemplate 的get方法有以上幾個,可以分為兩類: getForEntity() 和 getForObject()
首先看 getForEntity() 的返回值類型 ResponseEntity
<T> ResponseEntity<T> getForEntity()
- 1
看一下 ResponseEntity 的文檔描述:
可以看到 它繼承了HttpEntity. 封裝了返回的響應信息,包括 響應狀態,響應頭 和 響應體.
在測試之前我們首先 創建一個Rest服務,模擬提供Rest數據,這里給出Controller層代碼,具體可以查看源碼,文章最后會給出:
/** * @author itguang * @create 2017-12-17 10:37 **/ @RestController public class UserController { @Autowired private UserService userService; @RequestMapping(value = "getAll") public List<UserEntity> getUser() { List<UserEntity> list = userService.getAll(); return list; } @RequestMapping("get/{id}") public UserEntity getById(@PathVariable(name = "id") String id) { return userService.getById(id); } @RequestMapping(value = "save") public String save(UserEntity userEntity) { return "保存成功"; } @RequestMapping(value = "saveByType/{type}") public String saveByType(UserEntity userEntity,@PathVariable("type")String type) { return "保存成功,type="+type; } }
測試: getForEntity
- 無參數的 getForEntity 方法
1 @RequestMapping("getForEntity") 2 public List<UserEntity> getAll2() { 3 ResponseEntity<List> responseEntity = restTemplate.getForEntity("http://localhost/getAll", List.class); 4 HttpHeaders headers = responseEntity.getHeaders(); 5 HttpStatus statusCode = responseEntity.getStatusCode(); 6 int code = statusCode.value(); 7 8 List<UserEntity> list = responseEntity.getBody(); 9 10 System.out.println(list.toString()); 11 return list; 12 13 }
- 有參數的 getForEntity 請求,參數列表,可以使用 {} 進行url路徑占位符
//有參數的 getForEntity 請求,參數列表 @RequestMapping("getForEntity/{id}") public UserEntity getById2(@PathVariable(name = "id") String id) { ResponseEntity<UserEntity> responseEntity = restTemplate.getForEntity("http://localhost/get/{id}", UserEntity.class, id); UserEntity userEntity = responseEntity.getBody(); return userEntity; }
- 有參數的 get 請求,使用map封裝參數
//有參數的 get 請求,使用map封裝參數 @RequestMapping("getForEntity/{id}") public UserEntity getById4(@PathVariable(name = "id") String id) { HashMap<String, String> map = new HashMap<>(); map.put("id",id); ResponseEntity<UserEntity> responseEntity = restTemplate.getForEntity("http://localhost/get/{id}", UserEntity.class, map); UserEntity userEntity = responseEntity.getBody(); return userEntity; }
通過斷點調試我們看下 返回的 responseEntity 的信息如圖:
因此我們可以獲取Http請求的全部信息.
但是,通常情況下我們並不想要Http請求的全部信息,只需要相應體即可.對於這種情況,RestTemplate提供了 getForObject() 方法用來只獲取 響應體信息.
getForObject 和 getForEntity 用法幾乎相同,指示返回值返回的是 響應體,省去了我們 再去 getBody() .
測試: getForObject
- 無參數的 getForObject 請求
//無參數的 getForObject 請求 @RequestMapping("getAll2") public List<UserEntity> getAll() { List<UserEntity> list = restTemplate.getForObject("http://localhost/getAll", List.class); System.out.println(list.toString()); return list; }
- 有參數的 getForObject 請求,使用參數列表
//有參數的 getForObject 請求 @RequestMapping("get2/{id}") public UserEntity getById(@PathVariable(name = "id") String id) { UserEntity userEntity = restTemplate.getForObject("http://localhost/get/{id}", UserEntity.class, id); return userEntity; }
- 有參數的 get 請求,使用map封裝請求參數
//有參數的 get 請求,使用map封裝請求參數 @RequestMapping("get3/{id}") public UserEntity getById3(@PathVariable(name = "id") String id) { HashMap<String, String> map = new HashMap<>(); map.put("id",id); UserEntity userEntity = restTemplate.getForObject("http://localhost/get/{id}", UserEntity.class, map); return userEntity; }
Post請求
了解了get請求后,Post請求就變得很簡單了,我們可以看到post有如下方法:
測試: postForEntity
- post 請求,保存 UserEntity 對像
//post 請求,提交 UserEntity 對像 @RequestMapping("saveUser") public String save(UserEntity userEntity) { ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/save", userEntity, String.class); String body = responseEntity.getBody(); return body; }
瀏覽器訪問: http://localhost/saveUser?username=itguang&password=123456&age=20&email=123@123.com
我們再次斷點調試,查看 responseEntity 中的信息:
- 有參數的 postForEntity 請求
// 有參數的 postForEntity 請求 @RequestMapping("saveUserByType/{type}") public String save2(UserEntity userEntity,@PathVariable("type")String type) { ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/saveByType/{type}", userEntity, String.class, type); String body = responseEntity.getBody(); return body; } // 有參數的 postForEntity 請求,使用map封裝 @RequestMapping("saveUserByType2/{type}") public String save3(UserEntity userEntity,@PathVariable("type")String type) { HashMap<String, String> map = new HashMap<>(); map.put("type", type); ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost/saveByType/{type}", userEntity, String.class,map); String body = responseEntity.getBody(); return body; }
我們瀏覽器訪問: localhost/saveUserByType/120?username=itguang&password=123456&age=20&email=123@123.com
就會返回: 保存成功,type=120