我不擅長戀愛,但我天生愛你。 --zhu
前言
1、WEB API兩種風格:程序導向(RPC)、面向REST(REST)
2、RPC:“控制器/操作方法”的形式把伺服器端的程式碼當成方法去呼叫。把HTTP當成傳輸資料的通道,不甘心HTTP謂詞。透過QueryString、請求報文給伺服器傳遞資料,狀態碼。比如:/Persons/GetAll、/Persons/GetById?id=8、/Persons/Update、/Persons/DeleteById/8
REST
按照HTTP的語義來使用HTTP協議。
1、URL用於資源的定位:/user/888、/user/888/orders;
2、HTTP謂詞:GET,POST(新增),PUT(整體更新),DELETE, PATCH(區域性更新)等;
3、什麼是“冪等”,例:DELETE,PUT,GET是冪等的,POST不冪等。
4、GET的響應可以被快取。
5、伺服器端要透過狀態碼來反映資源獲取的結果:404、403(沒有許可權)、201(新增成功)。
對比
RPC:業務驅動,自然,高效。
REST:要求開發人員對REST原則更瞭解、並且有更多的設計能力。
REST優點
1、透過URL對資源定位,語義更清晰。
2、透過HTTP謂詞表示不同的操作,介面自描述。
3、可以對GET,PUT,DELETE請求進行測試。
4、可以用GET請求做快取,提高響應速度。
5、透過HTTP狀態碼反映伺服器端的處理結果,統一錯誤處理機制。
REST缺點
1、真實系統的資源非常複雜,很難清晰地進行資源劃分,對技術人員的業務水平要求高。
2、不是所有的操作都能簡單地對應確定的HTTP謂詞中。
3、系統的進化可能會改變冪等性。
4、透過URL進行資源定位不符合中文使用者的習慣。
5、HTTP狀態碼個數有限。
6、有些環節會篡改非200響應碼的響應報文。
7、有的客戶端不支援PUT,DELETE請求。
如何選擇
1、REST是學術化概念,僅供參考。AWS,ES比較RESTful,阿里、騰訊卻也有很多不RESTful。
2、根據公司情況,進行REST的選擇和裁剪。
HTTP傳遞引數的三種方式
URL:適合定位;長度限制。 /user/delete
QueryString:靈活;長度限制。 /user?name=tom&age=18
請求報文體:靈活;長度不限制;不支援GET,DELETE。
三種方式的不同語義
URL:資源定位。
QueryString:URL之外的額外資料。
請求報文體:供PUT、POST提供資料。
實施指南
1、對於儲存、更新這些請求POST、PUT請求,把全部引數都放到請求報文中。
2、對於DELETE請求,要傳遞的引數就是一個資源的id,因此把引數放到QueryString中即可。
3、對於GET請求,一般引數的內容都不會太長,因此統一透過QueryString傳遞引數即可。對於可能引數內容超過URL限制的請求,由於GET、PUT請求都是冪等的,因此我們把請求改成透過PUT請求,然後透過報文體來傳遞引數。
狀態碼
1、REST:透過HTTP狀態碼返回伺服器的處理結果。
2、問題:
1)HTTP狀態碼數量有限;
2)HTTP狀態碼並不適合用來表示業務層面的錯誤碼,它是一個用來表示技術層面資訊的狀態碼。新增使用者的操作中,如果伺服器要求Json格式,客戶端提交XML,伺服器返回400是沒問題的。但是如果使用者名稱格式錯誤,或者使用者名稱重複,存在200派和400派。
對於400(谷歌等):
1)閘道器等可以監控HTTP狀態碼,如果介面頻繁出現4xx狀態碼,那麼就說明客戶端程式碼不完善。
2)很多系統都是按照HTTP狀態碼的不同含義進行設計的。如果失敗了伺服器端返回狀態碼還是200的話,違背軟體設計初衷。
對於200(百度等):
網路問題歸網路,業務問題歸業務。業務錯誤不應該和技術錯誤混在一起。把系統日誌和業務日誌區分開。
傾向400
1、對於資料庫伺服器連線失敗、請求報文格式、伺服器端異常等非業務錯誤,伺服器端應該返回4xx、5xx等狀態碼。
2、對於業務層面的錯誤,比如使用者不存在,我們要使用4xx等HTTP狀態碼返回。同樣在響應報文體給出詳細的錯誤詳細,比如{"code":3,"message":"使用者不存在"}。
3、不僅要返回4xx的HTTP狀態碼,而且不要忘了透過響應報文體給出詳細錯誤資訊。對於使用者不存在,不僅要404,而且把響應報文體設定為{"code":3,"message":"使用者已存在"},這樣區分問題所在。
落地指南
1、使用RPC風格:Users/AddNew、Users/GetAll、Users/DeleteById.
2、對於可以快取的操作,使用GET請求;對於冪等的更新操作,使用PUT請求;對於冪等的刪除操作,使用DELETE請求;對於其他操作,統一使用POST請求。
3、引數:儲存、更新類的請求使用POST、PUT請求,把全部引數放到請求報文體;對於GET和DELETE請求,把引數放到QueryString中。推薦使用URL做資源定位。
4、對於業務錯誤,伺服器端返回適合的4xx狀態碼,不知道該選擇哪個狀態碼就用400;在報文體中透過code引數提供業務錯誤以及錯誤訊息。
實現技術
1、控制器上[Route("[controller]/[action]")]
2、強制要求控制器中不同的操作用不同的方法名
3、把[HttpGet]、[HttpPost]、[HttpDelete]、[HttpPut]等新增到對應的操作方法上。
4、如果控制器存在方法沒有新增[HttpGet]、[HttpPost]等的public方法,Swagger就會報錯,可以用[ApiExplorerSettings(IgnoreApi=true)]