欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

RESTful API接口設(shè)計規(guī)范與最佳實踐

admin
2023年11月29日 14:13 本文熱度 702

Part1介紹

RESTFull 接口設(shè)計目前廣泛應(yīng)用于各種軟件系統(tǒng)中,特別是前后端分離架構(gòu)的web應(yīng)用。相信各位web應(yīng)用的開發(fā)者對這個概念并不陌生,但是我們經(jīng)常會遇到幾個這樣的疑惑或者問題:

  1. 為什么這個接口只設(shè)計了GET和POST兩種請求類型?
  2. 為什么這個接口無論是否請求成功,HTTP狀態(tài)碼永遠只會是200?
  3. 當(dāng)一個查詢的結(jié)果為空的時候,為什么有的接口設(shè)計會返回異常(HTTP狀態(tài)碼404或其他),有的則是會返回請求成功(HTTPS狀態(tài)碼200),但是返回結(jié)果是空數(shù)組或者null等表示結(jié)果為空的標識?

以上這幾個問題,哪些是對的哪些是錯的呢?答案是:沒有對錯

在我們試圖搞清楚以上幾個問題之前,首先需要讀者了解或者閱讀過關(guān)于RESTfull的定義,這類定義百度一搜一大把這里就不重復(fù)贅述了。接著是最好你實踐過這類風(fēng)格設(shè)計的接口,如果你心中也同樣有這幾個問題或者疑問那就更好了,當(dāng)然最后這兩點要求并不是必須。

如果你已經(jīng)閱讀過關(guān)于RESTfull的相關(guān)定義,你就會發(fā)現(xiàn)RESTfull是一種接口設(shè)計風(fēng)格,它制定了一些原則條件,只要你遵守了,就算是RESTful風(fēng)格的接口設(shè)計。

那么問題就來了,這里面就存在很多靈活空間了,比如說我部分遵守,部分不遵守,可以嗎?可以。或者說我在遵守的基礎(chǔ)上,再自定義一些行為,可以嗎?可以。

各種諸如此類的實踐路線導(dǎo)致了我們很難在開發(fā)生涯中真的看到有兩個或更多的接口實現(xiàn)了一模一樣的RESTfull風(fēng)格接口,即便他們的業(yè)務(wù)是一樣的。這是因為RESTfull本身既然是一種設(shè)計風(fēng)格,那么風(fēng)格發(fā)揮的主動權(quán)自然就是在開發(fā)者身上,而且絕大多數(shù)的項目所開發(fā)的API接口都是對內(nèi)或者有限對外開放的,所以對于RESTfull的實踐是否合格更多取決于內(nèi)部團隊老大的看法。

說到這里讀者們可能會覺得,既然如此那這個真是太糟糕了,完全做不到統(tǒng)一,你完全想象不到別人設(shè)計出什么魔幻風(fēng)格的RESTfull接口,為什么RESTfull依然能成為主流的接口設(shè)計風(fēng)格呢?

這里我個人覺得有一部分原因是同行襯托,RESTfull基于HTTP協(xié)議,采用json格式的字符串作為傳輸內(nèi)容,相對于過去的SOAP協(xié)議,采用XML格式標記語言來說,RESTfull無論從開發(fā)成本或者網(wǎng)絡(luò)傳輸來說都顯得輕量太多太多。而前面提到的,關(guān)于實際開發(fā)出來的RESTfull接口風(fēng)格迥異的問題實際上并沒有太糟糕,為什么這么說呢?因為最起碼的一點是無論實際設(shè)計出來的接口再奇葩,總歸是基于HTTP協(xié)議和使用JSON字符串來傳遞數(shù)據(jù),這最起碼保證了我們在調(diào)用別人設(shè)計好的接口的時候足夠簡單。

當(dāng)然,能調(diào)用跟實際交互還有一段很長的距離,而中間這個過程你是否舒適,有一部分就體現(xiàn)在接口細節(jié)設(shè)計上了。按照一般的經(jīng)驗,像這種”標準化“的設(shè)計,我們會封裝一些基礎(chǔ)方法來實現(xiàn)接口的調(diào)用和數(shù)據(jù)接收,但現(xiàn)實卻是無法實現(xiàn)的。因為RESfull接口的具體實現(xiàn)細節(jié)上是因人而異的,這就導(dǎo)致了我們封裝的調(diào)用或者解析代碼未必能夠完全復(fù)用,很典型的例子就是我們一開始拋出來的那幾個問題。

這時候讀者們肯定想說,還是想吐槽,是的,我們可以吐槽一個接口設(shè)計得很糟心,讓我們調(diào)用起來很難受,但是我們又不可否認他確實遵守了RESTfull的基本規(guī)定,你可以發(fā)送一個HTTP請求,通過JSON來提交和接收數(shù)據(jù),你完全拿對方?jīng)]辦法。所以這也就是為什么我們一開始給出的答案是:沒有對錯。我們可以吐槽一個接口設(shè)計得非常糟糕,但是不能說這個接口不是RESTfull接口,但是,我們可以評判一個接口是否嚴格遵循了RESTfull風(fēng)格設(shè)計以及遵循的程度有多高。

我們可以從開局的幾個問題入手來嘗試評判下相應(yīng)的接口設(shè)計是否很好的遵循了RESTfull風(fēng)格設(shè)計。

Part2為什么接口只設(shè)計了GET和POST兩種請求方法類型?

解析:HTTP協(xié)常用的請求方法類型有GETPOSTPUTPATCHdelete,其中毫無疑問GETPOST是最最最常用的,而且每個請求方法類型都有各自的描述:

序號類型描述
1GET請求指定的頁面信息,并返回實體主體
2POST向指定資源提交數(shù)據(jù)進行處理請求(例如提交表單或者上傳文件)。數(shù)據(jù)被包含在請求體中。POST 請求可能會導(dǎo)致新的資源的建立和/或已有資源的修改
3PUT從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容
4PATCH是對 PUT 方法的補充,用來對已知資源進行局部更新
5delete請求服務(wù)器刪除指定的頁面

從上面的表格可以看出,不同類型的請求方法有著自己明確的含義,在理想的情況下,我們可以通過一個請求類型+請求地址的形式,直觀的看出一個接口的作用,比如:

// 猜猜阿克蘇我想干嘛
GET https://tinywan.com/users

delete  https://tinywan.com/users/69

這里讀者可以嘗試做一個閱讀理解。

那么這里問題就來了,既然HTTP的請求方法類型有助于我們理解一個接口的作用,為什么在有些接口中唯獨只會使用GET和POST呢?這里面我覺得原因有很多,有些可能我也想不到也猜不到,但是我從個人開發(fā)經(jīng)驗上嘗試猜測一下。

原因我覺得可能是一是懶,二是覺得沒必要,三是根本不會設(shè)計

坦白說,除了查詢請求這種無可爭議的使用GET之外,其他的全部歸為POST無疑是一件很方便的事。你不需要花時間去考慮接口的行為然后決定要定義成什么請求方法類型,反正具體的實現(xiàn)邏輯都是一樣的,而且POST方法的描述也似乎能涵蓋到其他幾個類型的請求方法。但這里讀者可能會說,在某些場景下會有歧義,比如說我們要調(diào)用一個接口實現(xiàn)刪除一個用戶:

  // 猜猜我想干嘛
  POST https://tinywan.com/users/69

這里我們復(fù)用了前面其中一道閱讀理解題并把類型改成了POST。這里第一眼看上去確實不能很好的表達接口的意圖,但是我們有接口文檔呀,我在相應(yīng)的接口名稱中寫清楚再放大字體說這個接口是刪除用戶用的不就完事了?這么一聽好像也有道理。所以綜合看來,細分各個方法請求類型似乎變成一件很多余的事,吃力不討好,干脆就GET/POST一把梭了。

說到這里,我們再回過頭來看看問題本身,做錯了嗎?沒有。那嚴格遵循了RESTfull風(fēng)格設(shè)計了嗎,那倒是并沒有。

RESTfull是基于HTTP協(xié)議的,HTTP協(xié)議里面清清楚楚明明白白提供了這些方法類型,那么從嚴謹?shù)慕嵌壬蟻碚f,我們確實是需要清楚的定義好每個請求的類型是什么。這不僅是有利于提高接口語義化,其實對接口地址定義也有些好處,比如說我們要定義一套對用戶進行CRUD的接口。

遵循 RESTfull

// 遵循RESTfull
GET     https://tinywan.com/users

GET     https://tinywan.com/users/1

POST    https://tinywan.com/users
Body:   "{"username":"Tinywan","password":123446}"

PUT     https://tinywan.com/users/1
Body:   "{"username":"阿克蘇","password":wt@123465}"

PATCH   https://tinywan.com/users/69
Body:   "{"password":999999}"

delete  https://tinywan.com/users/1

不遵循RESTfull

GET     https://tinywan.com/users

GET     https://tinywan.com/users/1

POST    https://tinywan.com/users
Body:   "{"username":"Tinywan","password":123446}"

POST    https://tinywan.com/put/users/1
Body:   "{"username":"阿克蘇","password":wt@123465}"

POST    https://tinywan.com/patch/user/69
Body:   "{"password":999999}"

POST    https://tinywan.com/delete/user/1

注意:在不遵循RESTfull風(fēng)格的情況下,因為除了GET以外都是POST類型請求,我們需要為相同POST請求的接口定義不同的路由地址,這里示例中的路由地址只是為了體現(xiàn)這一點,真實開發(fā)場景中如何命名各有各發(fā)揮。

從這里的示例可以看出,在不遵循RESTfull風(fēng)格設(shè)計的情況下我們難免需要在接口URL地址中增加一些描述性的單詞,這會導(dǎo)致路由接口地址變得很冗長和不夠優(yōu)雅,當(dāng)然如果你覺得這不是什么問題那也是沒錯的,對,你沒錯。

最后總結(jié)一下這個問題就是,你可以不遵循RESTfull風(fēng)格設(shè)計里面關(guān)于對請求方法類型的區(qū)分定義,但需要在路由地址上花心思,那么在真實開發(fā)場景中,我們該如何選擇呢?我的建議是如果你能做主,而且覺得有必要,就嚴格遵循,反之,領(lǐng)導(dǎo)說就啥吧。

Part3為什么接口是否請求成功,HTTP狀態(tài)碼永遠只會是200?

解析:常見的HTTP狀態(tài)碼有如下幾種:

狀態(tài)碼英文名稱描述
200OK請求成功。一般用于GET與POST請求
201created已創(chuàng)建。成功請求并創(chuàng)建了新的資源
400Bad Request業(yè)務(wù)錯誤,語義有誤,當(dāng)前請求無法被服務(wù)器理解
401Unauthorized認證失敗,當(dāng)前請求需要用戶驗證
403Forbidden無權(quán)限調(diào)用接口,服務(wù)器已經(jīng)理解請求,但是拒絕執(zhí)行它
404Not Found服務(wù)器無法根據(jù)客戶端的請求找到資源(網(wǎng)頁)。通過此代碼,網(wǎng)站設(shè)計人員可設(shè)置"您所請求的資源無法找到"的個性頁面
429Has Many請求次數(shù)超過限定次數(shù)(目前限定一分鐘6次請求)
500Internal Server Error服務(wù)器內(nèi)部錯誤,無法完成請求

從上面表格可以看出,HTTP碼是用于標識本次請求響應(yīng)的結(jié)果狀態(tài),通過HTTP狀態(tài)我們可以直觀的判斷出本請求是不是成功的,但是為什么有些接口設(shè)計的情況是無論成功與否都只會返回200的狀態(tài)碼呢?

這里的原因和第1點的問題大致相同,就是懶和覺得沒必要。但相對于明確方法請求類型來說,明確接口響應(yīng)的HTTP狀態(tài)碼卻是大有意義。

首先假設(shè)我們把所有請求響應(yīng)的HTTP狀態(tài)碼都標識為200,那么我們必然需要在響應(yīng)內(nèi)容中增加一些字段來描述本次錯誤,例如:

// 200
{
  // 定義一個錯誤碼
  "code": 1024,
  // 錯誤碼對應(yīng)的錯誤信息描述
  "message""密碼不正確"
}

這里大家可能會覺得,我們已經(jīng)有code和message字段來描述本次請求的錯誤了,完全不需要HTTP狀態(tài)碼。這里乍一看是沒有問題的,前端也能在統(tǒng)一異常處理的層面很好的捕獲異常。

但是,當(dāng)你的系統(tǒng)到了一定的規(guī)模(這個很容易達到,并不要求需要多大的規(guī)模體量,只要不是demo項目),你的錯誤類型就會有很多種,往往我們的錯誤碼清單會很長,當(dāng)然這對于后端開發(fā)來說不是啥問題,因為這個信息其實是給前端開發(fā)者處理的,但是前端開發(fā)者在處理這些錯誤的時候就難受了。

難受在哪?假設(shè)我們現(xiàn)在有10個關(guān)于賬戶異常的錯誤碼,10個關(guān)于業(yè)務(wù)A的錯誤碼,10個關(guān)于業(yè)務(wù)B的錯誤碼,一共30個。這里面有個業(yè)務(wù)需求,就是某些特定的錯誤碼需要前端做出特定的行為,比如說跳轉(zhuǎn)到指定頁面,或者強制退出啥等等。那么這時候前端在統(tǒng)一異常處理的時候咋做?那就是各種if/elseswitch判斷。

看起來似乎也問題不大嘛,是的,接著我們需求變了,和原來不一樣了,原來的分支判斷條件可能不適用了,錯誤碼改了,含義不一樣了,或者又增加了30個新的錯誤碼,那么這時候前端開發(fā)者就炸了。

所以從這里可以看出,單純依靠錯誤碼來實現(xiàn)前端統(tǒng)一異常處理依然會存在重復(fù)編碼問題,那么如果我們嚴格遵循RESTfull風(fēng)格設(shè)計的話,增加HTTP狀態(tài)碼的區(qū)分定義,同時保留原來的錯誤響應(yīng)信息結(jié)果會是如何?這時候前端開發(fā)者在做統(tǒng)一異常處理的時候,先按狀態(tài)碼做一層大范圍的分支處理,再有針對性的對這個狀態(tài)碼類型下的某些錯誤碼做特殊處理即可。

這兩種方式的區(qū)別在于,通過HTTP狀態(tài)碼相當(dāng)于給錯誤碼做了一個歸類,這也符合真實開發(fā)場景的異常處理情況。多數(shù)情況下前端在對異常做統(tǒng)一處理的時候,同一類型的異常往往后續(xù)的處理行為是一致的。

比如說給后端傳遞了錯誤的參數(shù),這種一般后端在校驗不通過的時候,會返回的HTTP狀態(tài)碼是400。這類提示信息是需要把具體錯誤信息展示給用戶作為警告提示的,那么前端開發(fā)者在統(tǒng)一異常處理的時候,只需要判斷HTTP狀態(tài)碼是不是400,是的話直接把具體內(nèi)容以各種彈出提示的形式展示即可,不用關(guān)心具體的錯誤碼又是什么(需要特殊處理的除外)。還有一種是401和**403 **HTTP狀態(tài)碼的錯誤,這兩種都是跟權(quán)限有關(guān)的錯誤,前端開發(fā)者在做統(tǒng)一異常處理的時候也可以進行針對性的統(tǒng)一捕獲處理。

從上面舉的一些例子可以看出,相同的HTTP狀態(tài)碼,前端的處理行為往往是一致的,但錯誤碼未必。

相對于單純依靠錯誤碼,HTTP狀態(tài)碼+錯誤碼的方式讓前端開發(fā)者更容易實現(xiàn)封裝和統(tǒng)一處理,前端開發(fā)者根據(jù)HTTP狀態(tài)碼定義不同的響應(yīng)處理,可以大大減少開發(fā)工程量和降低溝通成本。但是這里讀者們可能會說,我們可以把錯誤碼按范圍劃分,實現(xiàn)比如1~99是代表XX類型錯誤,100~199是XX類型錯誤。這個確實可以,但是這等于是換了條路開倒車,其實還是會有一開始的提到的痛點問題出現(xiàn)。而且錯誤碼因為是團隊定義的,如果維護不善會導(dǎo)致各種前后端開發(fā)者信息不同步的問題,既然通過HTTP狀態(tài)碼的定義就能解決大部分問題了為什么不用呢?

最后總結(jié)一下這個問題就是,強烈建議嚴格按照HTTP狀態(tài)碼的定義區(qū)分接口響應(yīng)的HTTP狀態(tài)碼,錯誤碼作為一種細分的補充。

Part4HTTP狀態(tài)碼不存在,返回 200 還是 404 ?

問題: 當(dāng)一個查詢的結(jié)果為空的時候,為什么有的接口設(shè)計會返回異常(HTTP狀態(tài)碼404或其他),有的則是會返回請求成功(HTTPS狀態(tài)碼200),但是返回結(jié)果是空數(shù)組或者null等表示結(jié)果為空的標識?

解析:這個問題情況有點特殊,理論上來說,當(dāng)我們查詢了資源然后結(jié)果是不存在的時候,這個時候用404的HTTP狀態(tài)碼來標識本次請求的響應(yīng)狀態(tài)是一點問題都沒有的,也是非常規(guī)范的做法。但是這是建立在業(yè)務(wù)場景規(guī)定,查詢結(jié)果為空的時候?qū)儆诋惓5那疤嵘稀?/p>

1返回HTTP狀態(tài)碼 200

當(dāng)我們查詢一個資源但是結(jié)果為空,到底要不要把本次請求視為一個404的異常是取決于業(yè)務(wù)場景。如果說業(yè)務(wù)場景認為”空“是允許的,那么就不應(yīng)該讓本次響應(yīng)是一個404的HTTP狀態(tài)碼,因為有些業(yè)務(wù)場景下,“空”也是有它的業(yè)務(wù)含義的

比如我們要查詢一個月內(nèi)連續(xù)登陸10天的用戶列表,結(jié)果是沒有用戶滿足這個條件,那么我返回的結(jié)果自然是空的,并不能視為一個異常,這時候返回一個200的HTTP狀態(tài)碼,然后在響應(yīng)結(jié)果里面明確結(jié)果是空的才是正確的做法。

2返回HTTP狀態(tài)碼 404

那么什么場景下”空“是不允許的呢?比如說我們要修改指定的某個用戶的個人信息,那么通常情況下我們后端的處理邏輯是這樣的:查詢這個用戶是否存在,如果存在則進行更新操作,如果不存在,拋出一個異常提示要修改的用戶不存在。在這種場景下,這個異常就會是一個404異常,我們嘗試修改一個并不存在的用戶。

最后總結(jié)一下這個問題,當(dāng)請求的結(jié)果為空時,是不是屬于異常要考慮業(yè)務(wù)場景,并且這個劃分定義也是很有必要的,可以避免潛在的業(yè)務(wù)理解偏差導(dǎo)致的程序執(zhí)行邏輯問題,因為如果是一個異常,那么會更早的被前端在統(tǒng)一異常處理里面的捕獲并處理,有利于前、后端開發(fā)人員開發(fā)出更健壯的系統(tǒng)。


該文章在 2023/12/7 11:37:56 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved