非RESTful風格問題
七宗罪的第一條,混亂。
一萬個人心裏有一萬個Url的命名規則,Url是統一資源定位符,重點是資源。而很多人卻把它當成了萬金油,每一個獨立的虛擬的網頁都可以隨意使用,各種操作都能夠迭加。這是混亂的來源之一。
比如:
https://localhost:8080/myweb/getUserById?id=1
https://localhost:8080/myweb/user/getById?id=1
https://localhost:8080/myweb/x/y?id=1
第二條,貪婪。
有狀態和無狀態全部混在一起。特別是在購物車或者是登錄的應用中,經常刷新就丟失帶來的用戶體驗簡直棒棒噠。每一個請求並不能單獨的響應一些功能,很多的功能混雜在一起裏。這是人性貪婪的本質,也是各種Hack的起源,只要能夠把問題解決掉,總會有人用他認爲最方便的方式去解決問題,比如說汽車門把手壞掉了直接系根繩子當把手,emmmm這樣確實很棒啊。
第三條,無序。
返回的結果往往是很隨意,各種錯誤信息本來就是用Http的狀態碼構成的,可是很多人還是喜歡把錯誤信息返回在返回值中。最常見的就是Code和Message,當然對於這一點,我個人是保留疑問的,我的觀點是,Http本身的錯誤和服務器的內部錯誤還是需要在不斷層面分開的,不能混在一起。可是在大神眼裏並非如此。
對比
https://localhost:8080/myweb/getDogs --> GET /rest/api/dogs 獲取所有小狗狗
https://localhost:8080/myweb/addDogs --> POST /rest/api/dogs 添加一個小狗狗
https://localhost:8080/myweb/updateDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一個小狗狗
https://localhost:8080/myweb/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 刪除一個小狗狗
左邊是我們寫的,而且後臺我們可能會寫出很多返回值,而且各種各樣的,比如
https://localhost:8080/myweb/addDogs
操作成功 或者 1
1
或者
操作失敗 或者 0
1
這還要我們自己去解析,還要前端和後端去協商你返回的0是啥意識啊。但是REST返回值是標準的,比如
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx
{
"url" : "/api/categories/1",
"label" : "Food",
"items_url" : "/api/items?category=1",
"brands" : [
{
"label" : "友臣",
"brand_key" : "32073",
"url" : "/api/brands/32073"
}, {
"label" : "樂事",
"brand_key" : "56632",
"url" : "/api/brands/56632"
}
...
]
}
格式固定,第一行永遠是操作失敗或者成功的狀態碼,第二行是返回的類型,第三行內容的長度,第五行開始是內容。
這樣我只需寫一個程序解析返回的信息就可以了,可以重用,但是我們上面傳統的不僅僅要協商,還有有不同的解析程序,稍微改變,就不能正常使用了。所以rest的明顯更加通用。
列子2
1、獲取文章
請求:
GET /blog/post/{postId} HTTP/1.1
響應:
HTTP/1.1 200 OK
{
"title": "foobar",
"content": "foobar",
"comments": ["", "", ""]
}
2、發佈文章
請求:
POST /blog/post HTTP/1.1
{
"title": "foobar",
"content": "foobar",
"comments": ["", "", ""]
}
響應:
HTTP/1.1 201 CREATED
規則
GET 用來獲取資源,
POST 用來新建資源(也可以用於更新資源),
PUT 用來更新資源,
DELETE 用來刪除資源
例子
DELETE http://api.qc.com/v1/friends: 刪除某人的好友 (在http parameter指定好友id)
POST http://api.qc.com/v1/friends: 添加好友UPDATE
PUT http://api.qc.com/v1/profile: 更新個人資料
是什麼?
REST是一個標準,一種規範,遵循REST風格可以使開發的接口通用,便於調用者理解接口的作用。
概念
REST 是面向資源的,這個概念非常重要,而資源是通過 URI 進行暴露。
URI 的設計只要負責把資源通過合理方式暴露出來就可以了。對資源的操作與它無關,操作是通過 HTTP動詞來體現,所以REST 通過 URI 暴露資源時,會強調不要在 URI 中出現動詞。
比如:左邊是錯誤的設計,而右邊是正確的
GET /rest/api/getDogs --> GET /rest/api/dogs 獲取所有小狗狗
GET /rest/api/addDogs --> POST /rest/api/dogs 添加一個小狗狗
GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一個小狗狗
GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 刪除一個小狗狗
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx
{
"url" : "/api/categories/1",
"label" : "Food",
"items_url" : "/api/items?category=1",
"brands" : [
{
"label" : "友臣",
"brand_key" : "32073",
"url" : "/api/brands/32073"
}, {
"label" : "樂事",
"brand_key" : "56632",
"url" : "/api/brands/56632"
}
...
]
}
REST很好地利用了HTTP本身就有的一些特徵,如HTTP動詞、HTTP狀態碼、HTTP報頭等等
REST API 是基於 HTTP的,所以你的API應該去使用 HTTP的一些標準。這樣所有的HTTP客戶端(如瀏覽器)才能夠直接理解你的API(當然還有其他好處,如利於緩存等等)。REST 實際上也非常強調應該利用好 HTTP本來就有的特徵,而不是隻把 HTTP當成一個傳輸層這麼簡單了。
看這個響應,包含了http裏面的狀態碼等信息。還會有http的一些報頭。
Authorization 認證報頭
Cache-Control 緩存報頭
Cnotent-Type 消息體類型報頭
......
REST 系統的特徵
- 客戶-服務器(Client-Server),提供服務的服務器和使用服務的客戶需要被隔離對待。
- 無狀態(Stateless),來自客戶的每一個請求必須包含服務器處理該請求所需的所有信息。換句話說,服務器端不能存儲來自某個客戶的某個請求中的信息,並在該客戶的其他請求中使用。
- 可緩存(Cachable),服務器必須讓客戶知道請求是否可以被緩存。(Ross:更詳細解釋請參考 理解本真的REST架構風格 以及 StackOverflow 的這個問題 中對緩存的解釋。)
- 分層系統(Layered System),服務器和客戶之間的通信必須被這樣標準化:允許服務器和客戶之間的中間層(Ross:代理,網關等)可以代替服務器對客戶的請求進行迴應,而且這些對客戶來說不需要特別支持。
- 統一接口(Uniform Interface),客戶和服務器之間通信的方法必須是統一化的。(Ross:GET,POST,PUT.DELETE, etc)
- 支持按需代碼(Code-On-Demand,可選),服務器可以提供一些代碼或者腳本(Ross:Javascrpt,flash,etc)並在客戶的運行環境中執行。這條準則是這些準則中唯一不必必須滿足的一條。(Ross:比如客戶可以在客戶端下載腳本生成密碼訪問服務器。)
詳細解釋
無狀態(Stateless)
所謂無狀態的,即所有的資源,都可以通過URI定位,而且這個定位與其他資源無關,也不會因爲其他資源的變化而改變。有狀態和無狀態的區別,舉個簡單的例子說明一下。如查詢員工的工資,如果查詢工資是需要登錄系統,進入查詢工資的頁面,執行相關操作後,獲取工資的多少,則這種情況是有狀態的,因爲查詢工資的每一步操作都依賴於前一步操作,只要前置操作不成功,後續操作就無法執行;如果輸入一個url即可得到指定員工的工資,則這種情況是無狀態的,因爲獲取工資不依賴於其他資源或狀態,且這種情況下,員工工資是一個資源,由一個url與之對應,可以通過HTTP中的GET方法得到資源,這是典型的RESTful風格。
統一接口(Uniform Interface)
RESTful架構風格規定,數據的元操作,即CRUD(create, read, update和delete,即數據的增刪查改)操作,分別對應於HTTP方法:GET用來獲取資源,POST用來新建資源(也可以用於更新資源),PUT用來更新資源,DELETE用來刪除資源,這樣就統一了數據操作的接口,僅通過HTTP方法,就可以完成對數據的所有增刪查改工作。
即:
GET(SELECT):從服務器取出資源(一項或多項)。
POST(CREATE):在服務器新建一個資源。
PUT(UPDATE):在服務器更新資源(客戶端提供完整資源數據)。
PATCH(UPDATE):在服務器更新資源(客戶端提供需要修改的資源數據)。
DELETE(DELETE):從服務器刪除資源。
演化
https://zhuanlan.zhihu.com/p/30396391?group_id=937244108725641216
優點&缺點
優點:
-
適合開放性高的API。這幾年的由於移動互聯網流行使得前端設備多樣化,業界急需一種統一的機制來規範API設計,使得API適用於各種各樣的前端設備,REST符合這種需求。
-
行爲和資源分離,更容易理解
-
提出使用版本號(例如v1、v2),更加規範。
缺點
-
對後端開發人員要求高,業務邏輯有時難以被抽象爲資源的增刪改查。(例如批量刪除數據,等複雜的邏輯)。
-
對前端開發人員不友好,API粒度較粗,難以查詢符合特殊要求的數據,同樣的業務要比普通的API需要更多次HTTP請求。
參考文章:
https://blog.csdn.net/qq_21383435/article/details/80032375
https://www.zhihu.com/question/28557115
https://blog.igevin.info/posts/restful-architecture-in-general/