RESTful Web API 理解
REST 是一種應用架構風格,不是一種標準,是面向資源架構(ROA)風格,與具體技術平臺無關,REST架構的應用未必建立在Web之上,與之對應的是傳統的Web Service 采用的面向操作的RPC架構風格。
一、基礎概念
1、Web
為我們提供獲取和操作網絡資源的方式,資源包括文字、圖片、音頻、視頻;核心體現在三個方面,HTTP、超文本、超媒體,HTTP為網絡訪問的標準協議,超文本和超媒體,規範了網絡信息的表現形式,利用“鏈接”在相關資源節點間穿針引線結成一張非線性網,即Web。
2、網絡協議
(1)、IP協議
處於網絡層,無鏈接的網絡協議,傳輸不可靠且無序,數據完整性不能保證。
- 不可靠性,即不能保證發送出去的數據報文成功到達目的地。
- 無序,即每次數據報文處理都是獨立的。
- 數據不完整性,接收方沒有根據報文段的校驗和來檢查數據在傳輸過程中是否被篡改。
(2)、TCP協議
位於網絡層之上的傳輸層,基於連接的傳輸協議,解決了IP協議不可靠性,無序性,不完整性三個問題。數據交換雙方在在數據報文傳輸前先建立一個雙工連接,雙方都可以用它來發送數據,在報文傳輸結束後關閉連接。
- 可靠性,借助“接收確認”和“超時重傳” 機制來實現,發送方有個緩沖區,用來存放發送出去但還未確認的保文,超過指定時限會重發,接收到確認消息就在緩沖區刪除。
- 有序性,報文編號機制,每個數據報文都有個編號,其體現了報文的順序,接收方接收到一個報文後,根據其編號先確認其之前編號的報文都接收了,才往應用層提交報文數據,判斷標準是其記錄一個上次成功遞交給應用層的報文編號,如果此次接收報文的編號和上次是連續的說明是有序的,否則說明之前還有報文未接收。接收方也有個緩沖區,用來存放接收但不能向應用層提交的保文,等之前發送的所有報文都接收到之後,按序號順序往應用層提交報文,再從緩沖區中把其刪除。另外,重復的報文會被丟棄,判斷重 復的標準是,報文的序號小於最後遞交給應用層的報文編號或者添加到緩沖區的報文編號。
- 數據完整性,報文段有個16位的校驗和(Checksum),接收方可以根據它來確認數據在傳輸過程中是否被篡改。
- 報文不丟失,借助“流量控制”機制,發送和接收方緩沖區大小不一致會導致發送後的報文會丟失,如果發送方緩沖區比接收方大,其實根據緩沖區大小來發送報文的,因為緩沖區存放了發送的而且未接收的,接收方緩沖區滿了後,不能處理後續接收的報文,所以接收方會及時通知發送方緩沖區剩余大小,發送方根據其來控制流量。
(3)、HTTP協議
位於傳輸層之上的應用層,其基於傳輸層的TCP可靠傳輸協議,提供了可靠數據傳輸的保障。是一種無狀態的網絡協議,采用簡單的“請求/響應”消息交換模式,不會保存多次消息交換的會話狀態,每次消息交換都是相互獨立的,開始於請求發送,止於響應接
收,每次消息交換都是一次完整的事物。
IP協議根據IP地址定位數據目的地,TCP協議利用端口標識應用程序,應用程序間通訊需要指定IP地址和端口。
3、資源
(1)、定義
寄宿於Web(服務器)、通過HTTP協議獲取或操作的“事物“,可以是磁盤上的文件、數據庫裏的記錄,算法計算出的結果,可以使具體的事物,也可以是抽象的流程。
(2)、標識
可操作資源應該具有一個或多個唯一標識。標識的類型可以采用GUID,但是URI是達成共識的公認標準。URL和URN都是URI的一種表現形式。
(3)、URL
統一資源定位符,用來定義資源的唯一標識、位置、獲取方式(協議,如HTTP)。
http://www.myhost.com/employees/001
001號員工資源的唯一標識,位置在www.myhost.com服務器上,通過HTTP協議獲取
4、媒體類型
資源是一種數據,其承載了某種信息(內容含義,比如部門所有員工),相同的信息可以用不同數據形態或數據格式來展現,這種數據格式稱為媒體類型,比如相同的部門員工,可以用XML格式,也可以用JSON格式來展示。
媒體類型又稱MIME類型,常用的媒體類型有,text/html,text/xml,text/json,image/gif,audio/mp4,video/mp4.
5、HTTP方法
資源用URI來標識,對資源的操作類型通過Http方法來指定。常見方法有以下幾種:
- Get:獲取資源。
- Head:獲取描述資源的元數據信息。
- Option:探測請求,確定某個目標地址的真實請求應該具有怎麽樣的約束,如采用怎麽樣的Http方法或必須攜帶怎麽的自定義報頭,然後根據其約束發送符合條件的請求。“跨域資源”的預檢請求采用的就是Options方法。
- Post:添加一個新資源
- Put:添加或修改一個資源,存在就修改,否則添加,這裏的修改是完整修改
- Patch:部分修改,補丁的意思
- Delete:刪除資源
6、HTTP響應狀態碼
- 1XX:請求已被接受,並須繼續處理,100-199
- 2XX:請求被成功處理, 200-299
- 3XX:重定向,需要客戶端采取進一步的操作才能完成請求, 300-399
- 4XX:客戶端錯誤,因客戶端發生錯誤而妨礙了服務器的處理, 400-499
- 5XX:服務端錯誤, 500-599
7、HTTP報文
分請求報文和響應報文,內容都是包含,起始行、報頭集合(空行表示結束)、主題內容,如
- 請求報文
GET http://www.myhost.com/employees/001 HTTP/1.1 起始行
Accept:text/html,application/xml... 報頭集合
...
空行
空 主體內容
- 響應報文
HTTP/1.1 200 OK 起始行
Content-Type:text/html;charset=utf-8 報頭集合
....
空行
<!DOCTYPE... 響應主題內容
8、超媒體/超文本
超文本是與其它數據有關聯(Links)的數據。包含與其他文檔鏈接的文檔;選擇鏈接時自動顯示第二個文檔。
超文本可利用引用鏈接其他不同類型(內含聲音、圖片、動畫)的文件,這些具有多媒體操作的超文本,稱為超媒體(HyperMedia),意指多媒體超文本(Multimedia Hypertext),即以多媒體的方式呈現相關文件信息。
超媒體的核心是利用“鏈接”將相關的信息結成一個非線性的網。
9、REST(表現/應用狀態轉換)
REST定位為“分布式超媒體應用”的架構風格。
應用狀態即WEB應用的客戶端狀態。
資源在瀏覽器中以超媒體的形式呈現,通過單擊超媒體中的鏈接可以獲取其他相關資源或對當前資源進行相應處理,獲取的資源或者針對資源處理的響應同樣以超媒體形式再次呈現在瀏覽器上。
借助於超媒體這種特殊資源呈現方式,應用狀態的轉換體現為瀏覽器中呈現資源的轉換,應用狀態變為了可呈現的狀態,應用狀態的轉換變成了可呈現的狀態轉換,即REST。
二、RESTful Web API 特性
對於多個應用采用的架構,我們只能說其中一個比其他的更具有REST風格。以下是ROA架構的Web API應該具備的基本特征,是指導方針。
1、URI標識資源
URI具有標誌性、可讀性、可尋址性。可表示單個資源,也可以表示多個資源的集合。
http://www.myhost.com/employees/001 編號為001的員工
http://www.myhost.com/sales/2017/12/03 2017年12月3號的銷售額
http://www.myhost.com/orders/2017/q4 2017年第四季度的訂單(資源集合)
2、使用鏈接關聯相關資源
資源一般不是單獨存在,與其他資源有某種關聯,通過超文本/超媒體文檔中的鏈接關聯相關資源;我們是用URL來標識資源的,文檔中的鏈接采用URL地址來鏈接到其他資源,其可以使資源地址,也可以是對資源的操作鏈接。比如一份XML文檔中,包含一些其他資源的引用。客戶端獲取該文檔在瀏覽器展現,並根據文檔中引用生成一些鏈接,這些鏈接地址都是Web API 地址,供用戶操作.
3、使用統一的標準資源操作接口(CRUD)
這是RESTful Web API 和RPC風格面向功能操作集合的SOAP Web Service的Web API區分的一個主要特征。URI中不包含動詞,動詞使用HTTP謂詞(Method)。返回結果影響到接口的統一性,要求所有的返回碼必須通過HTTP狀態碼來返回,另外,客戶端從服務端取得的不是資源本身,而是資源的表現形式。
標準接口即為不同(資源)Web API定義一致性的操作來管理各自的資源,從資源角度去組織接口,而且不同資源操作都一致,不像RPC風格的Web API 只是從功能操作角度去考慮和組織操作。
一致的操作即CRUD,如下
public class ResourceService
{
public IEnumerable<Resource> Get();
public void Create(Resource resource);
public void Update(Resource resource);
public void Delete(string id);
}
另外,一個Web API 來管理角色的增刪查,以及建立和刪除角色和用戶之間的映射關系。RPC、SOAP風格的Web API 定義如下:
public class RoleService
{
public IEnumerable<string> GetAllRoles();
public void CreateRole(string roleName);
public void DeleteRole(string roleName);
public void AddRolesInUser(string userName, string[] roleNames);
public void RemoveRolesFromUsers(string userName, string[] roleNames);
}
其實,其中包含兩種資源,角色和角色委派,改成統一接口
public class RoleService
{
public IEnumerable<string> GetAllRoles();
public void CreateRole(string roleName);
public void DeleteRole(string roleName);
}
public class RoleAssignmentService
{
public void Create( RoleAssignment roleName);
public void Delete( RoleAssignment roleName);
}
統一接口方法名,類名隱含了資源類別,不同資源操作,組織到不同類中,采用統一的接口,而不是像RPC風格接口,統一放一個類裏,通過不同方法名區分。
4、使用標準的HTTP方法
常用就是前邊列出的其中Http方法,比如新增資源
POST http://www.myhost/employees HTTP/1.1,請求主體中附上資源內容
另外,HTTP方法具有兩個基本特性,安全性和冪等性。
GET、HEAD、OPTIONS是安全方法,只是獲取數據,沒有邊界效應或副作用,另外四個方法,POST、PUT、PATCH、DELETE會導致服務器資源變化,所以是不安全的。
冪等性,即發送一次和多次請求引起的邊界效應或副作用是一樣的。設計API時候,盡量根據請求HTTP方法的冪等性來決定處理邏輯。
GET、HEAD、OPTIONS是冪等方法,DELETE和PATCH也是冪等的,都是對現有的某個資源操作,多次操作效果都一樣,POST多次操作會增加多個資源,所以不是冪等的,PUT一般情況下也是冪等的,因為第一次不存在時候會添加,第二次操作存在了只會修改,對於PUT在特殊情況下是非冪等的,對於每次修改操作都修改一個版本號,但是有時候這種非冪等性不是非常重要。
5、多種資源表示方式(內容協商機制)
資源根據媒體類型有不同的表現形式,每次請求可以設定需要哪種資源的表示形式,如是需要XML還是JSON格式的資源。
通常是利用”內容協商機制”來實現,在請求報頭,Accept和Accept-language設置它所希望的資源表示,即媒體類型和語言。
還有種方式是在URL中包含資源表示。
6、無狀態性
RESTful只維護服務器上資源狀態,而不維護客戶端的狀態;Web API 不記錄客戶端的以前的請求狀態,其由客戶端自己來維護。如分頁號,Web API 不會知道上次的請求分頁號,它只會根據傳入的當前分頁號來處理,上次分頁號有客戶端自己處理。是無狀態的,減除了客戶端親和度,集群環境中有效實施負載均衡,每一臺部署了WEB API接口的服務器對每個客戶端都是等效的。
三、如何設計友好的REST API
1、URI
URI一般由名稱和id組成
(1)、單層資源:
/users 所有的用戶列表
/users/1 id為1的用戶
註意:名稱為復數users , id最好為uuid,使用簡單、無鎖,分布式系統中獨立處理,各自插入數據,不用擔心id沖突。
(2)、多層資源
/users/1/files 用戶1的所有文件
/users/1/files/2 用戶1的文件中id為2的文件
層數和參數不要太多,使用起來不方便,2層足夠
(3)、查詢參數不要放在URI中
/users/age/20/60 不好
/users?minAge=20&maxAge=60 寫成url參數
2、資源拆分
資源與領域類具有相當高的對應關系。
3、資源命名
(1)、資源名稱應該是名詞或動名詞形式,不要使用動詞
比如創建和註銷安全令牌 設計成 POST /tokens DELETE /tokens/{id}
(2)、註意名稱的表意性,恰如其分的表示業務含義,不要太啰嗦
files而不要寫成userFiles 太啰嗦
(3)、不要使用縮寫詞,避免使用有歧義或自創的所寫詞。
4、方法
(1)、安全性
安全性指的是一項操作不會改變資源的狀態,該操作應該把資源看成只讀。GET、HEAD是安全的,POST、PUT、DELETE、PATCH是不安全的。
但是,不是說不改變資源的狀態,就不能改變服務器任何東西,比如GET方法中可以記錄日誌,不違反規範。
一般對安全的請求進行緩存,所以可以充分利用互聯網的各級緩存設施。
如果你的GET方法會改變資源狀態,很容易遭受到攻擊,比如,GET請求進行投票,這樣把GET方法的地址發到論壇或QQ群裏,有人點擊,就可以投票了。
(2)、冪等性
意義在於安全的自動重試剛才的操作,而不用擔心破壞業務邏輯。
例如,瀏覽器中普通頁面可以隨意刷新,表單提交的頁面刷新會彈出一個警告,問你是否確實要重試,這是因為POST操作是不冪等的,自動重試會導致預期之外的結果。
GET是冪等的,無論執行多少次都沒區別,
POST不是冪等的,再執行一次會創建一個新的資源
DELETE 冪等的 ,用相同的數據去更新資源,無論執行多少次,其效果都一樣
5、返回值
REST風格中,成功、失敗等錯誤碼應該在響應頭中作為HTTP Status code 返回,不能在響應體中返回,這是HTTP規範也是REST規範要求。
我們可以在前端寫一個過濾層,對服務端的錯誤信息進行統一處理,AOP攔截。
出處:https://www.cnblogs.com/shawnhu/p/7891416.html
RESTful Web API 理解