不要以為 RESTful Api 就是設計得像便於 SEO 的偽靜態,例如一個 Api 的 URL 類似於 http://xxx.com/blog/1 ,我們可以通過瀏覽器訪問該 URL 而讀取文章,但是這並不代表著它就是 RESTful Api 。
也不要認為URL 裡有 queryString 就不是 RESTful Api ,例如 http://xxx.com/users/?page=10&page_size=30
更不要認為 HTTP + JSON 就是 RESTful ApI 了。
REST 和 HTTP/1.1Roy Fielding (Apache HTTP 伺服器的核心開發者,Apache 軟體基金會的合作創始人,HTTP/1.1 協議專家組的負責人)總結了一套理論框架,然後使用這套理論框架中的指導原則,來指導HTTP/1.1協議的設計方向。後來他在其的博士學位論文 Architectural Styles and the Design of Network-based Software Architectures 中更為系統、嚴謹地闡述了這套理論框架,並且使用這套理論框架推導出了一種新的架構風格,並且為這種架構風格取了一個令人輕鬆愉快的名字 REST。
想必通過這個你已經明白了 REST 和 HTTP/1.1 的密不可分的關係了吧。HTTP/1.1 的很多特性就是 REST 的特性,比如連接的無狀態性。還有後面說的 REST 五大特性都和 HTTP/1.1 協議密不可分。
RESTful Api 與 SOAP Web API 在 URL 形式上的對比從設計一個刪除評論的 api 說起我們可以這樣設計成類似於:
http://mengkang.net/?method=comment.del&id=x ①
http://mengkang.net/comment/del/id/x ②
或者其他形式的 url。
而 RESTful Api 則是:
[DELETE] http://mengkang.net/comments/1 ③
我們對比可以發現①和② URL 中,都有del的動作指示。
SOAP Web API採用RPC風格,它採用面向功能的架構,所以我們在設計SOAP Web API的時候首相考慮的是應高提供怎樣的功能(或者操作)。
而 RESTful Api 是面向資源的架構。是查詢、新增、修改、刪除,都該資源無關。
所以我們在③ URL 中沒有看到del的關鍵字,對比②和③最為明顯。
進一步認識 RESTful Api我們知道 URL 全稱為「統一資源定位符(Uniform Resource Locator)」,用於描述 Web 資源所在的位置。RESTful Api 是以 HTTP 協議為強烈依託的,將類似於①和②這種以功能為主導的URL風格捨棄,還原 URL 的本質,它的宗旨就是一個 URL 就應該是一個資源,不能包含任何動作。
[POST] http://mengkang.net/users // 新增
[GET] http://mengkang.net/users/1 // 查詢
[PATCH] http://mengkang.net/users/1 // 更新
[PUT] http://mengkang.net/users/1 // 覆蓋,全部更新
[DELETE] http://mengkang.net/users/1 // 刪除
PUT和PATCH的功能都可以代表更新,但略有不同,PUT大多時候表示更新該資源的全部信息,而PATCH則更新部分信息。
PUT和POST又一些功能的重疊,都可以是新建一個資源,POST時,新建資源的地址是由伺服器返回給客戶端的。也就是說客戶端在發送POST請求資源之前還無法預知該資源的地址,這在我們的 Api 開發中非常常見,新建一個帖子,新建一條評論,都如此。
而資源的地址是客戶端預先知道的情況則比較少。也有人如此設計而使用PUT,比如需要對 github 上的某人的項目 star ,則可能會設計成:http://github.com/xxx/zhoumengkang/projectname/star
這裡把「對這個項目已經點讚過」看成了一個資源,那麼就可以用PUT,因為要刪除這個資源時,還是訪問這個 URL。
關於這些功能上有交集的地方,可能後面會有一些更加標準的規範或者協議吧。
最後說下HEAD和OPTIONS,HEAD請求的是資源的元數據,比如一張照片,的元數據則可能包含了,照片拍攝的設備,地點,時間等。伺服器一般將對應資源的元數據置於響應的報頭集合返回給客戶端,這樣的響應一般不具有主體部分。OPTIONS則是發送一種「探測」請求以確定針對某個目標地址的請求必須具有怎樣的約束(比如應該採用怎樣的HTTP方法以及自定義的請求報頭),然後根據其約束髮送真正的請求。
關於過濾篩選,排序和 token 等 query string 是支持使用,和唯一資源的概念並不衝突。
我所理解的無狀態性和唯一資源對 Api Url 的設計指導舉一個實際的例子,用戶黑名單的 CURD。我們可是設計成
[GET] /blacklist
[PUT] /blacklist/{id} #把 id 加入到當前授權用戶的黑名單中
[DELETE] /blacklist/{id}
如上的 api 設計中,首先如上的 url 設計中,通過授權碼中獲取登錄用戶 uid。則是有狀態的了,其次因為所有的用戶訪問的資源都是同一個地址,這與唯一資源的概念是相違背的。如果是無狀態的,那麼就與唯一資源的概念相吻合了。(這只是 restful 所建議的,實際是否需要完全遵守視情況而定)
[GET] /user/{uid}/blacklist
[PUT] /user/{uid}/blacklist/{id} #把 id 加入到當前授權用戶的黑名單中
[DELETE] /user/{uid}/blacklist/{id}
資源(Resource)
資源的表述(Representation)
狀態轉移(State Transfer)
統一接口(Uniform Interface)
超文本驅動(Hypertext Driven)
資源的概念是 RESTful 裡面最重要的一個概念,很容易被我們忽視和誤解,所以就重點闡述了這一特性。
Server 端代碼的基本設計思想按照 RESTful Api 的規範,嚴格來說根據endpoint找到在 server 端映射成一個資源對象,例如通過 http://mengkang.net/users/1 找到UserResource對象
而在這個對象裡對應著該資源支持的 Http 協議的方法。如果一個對象支持7種方式的請求,則類似於:
public class UserResource {
private User user;
public UserResource() {
}
public UserResource(int id) {
//從數據查詢處該用戶的數據
String name = "xxx";
short age = 23;
user = new User(id,name,age);
}
/**
* 獲取單個用戶
* 從 new UserResource(int) 開始
* @return
*/
public User get(){
return user;
}
/**
* 覆蓋用戶的全部信息
* 從 new UserResource(int) 開始
* @return
*/
public boolean put(){
return true;
}
/**
* 只更新用戶的部分信息
* 從 new UserResource(int) 開始
* @return
*/
public boolean patch(){
return true;
}
/**
* 創建一個 UserResource
* @return
*/
public int post(){
return 1;
}
/**
* 刪除用戶
* @return
*/
public boolean delete(){
return true;
}
}
如果有關注的 api 那麼對於該用戶的 star 操作則應新建一個UserStarResource資源對象,因為每個資源最多只有這7中方法,構造方法除外,而不能有其他的相關的動作方法。
假如我們規定 URL 為 http://mengkang.net/user/1/star 表示是訪問者對 id 為 1 的這個用戶的 star 狀態的一個資源。(當前訪問者的信息通過 query string 傳遞 auth token 的形式獲取)
public class UserStarResource {
public boolean get(){
return true;
}
public boolean post(){
return true;
}
public boolean delete(){
return true;
}
}
理論上來說我們應該以 Http response status code 作為客戶端的標準,而不是在 Http body 體裡面定義。這樣客戶端的能夠更快速的獲取服務端的響應狀態碼。
但是由於國內某些網絡商會劫持狀態碼非200的請求,跳轉到他們的廣告地址。所以大家還是考慮國內的實際情況。
REST 架構風格約束客戶-伺服器(Client-Server)通信只能由客戶端單方面發起,表現為請求-響應的形式。
無狀態(Stateless)通信的會話狀態(Session State)應該全部由客戶端負責維護。
緩存(Cache)響應內容可以在通信鏈的某處被緩存,以改善網絡效率。
統一接口(Uniform Interface)通信鏈的組件之間通過統一的接口相互通信,以提高交互的可見性。
分層系統(Layered System)通過限制組件的行為(即,每個組件只能「看到」與其交互的緊鄰層),將架構分解為若干等級的層。
以上內容希望幫助到大家,有需要的可以添加下方二維碼進群交流學習新技術。
來源:
https://blog.csdn.net/jj546630576/article/details/77948445
好文連接:
優化MYSQL查詢步驟,提高你的20%的工作效率
PHP使用swoole改造laravel應用
如果你想和PHP大神交流,添加微信,拉你入群
如果你想獲得更多學習資料,添加微信,送你資源