Spring基礎(chǔ)篇(5)-restful命名規(guī)則

JAVA && Spring && SpringBoot2.x — 學(xué)習(xí)目錄

上來一首打油詩(shī):
動(dòng)詞加名詞,名詞用復(fù)數(shù)佛南。
動(dòng)詞分五類,之間可覆蓋嵌言。
名詞若多級(jí)嗅回,從屬或平等。
狀態(tài)需明確摧茴,響應(yīng)給連接绵载。

1. 什么叫做Restful

簡(jiǎn)單來講:Restful是一種框架的規(guī)范與約束原則,符合這種規(guī)范的架構(gòu)都是RESTful架構(gòu)

1.1 RESTful是什么意思苛白?

REST是Representational State transfer (資源)表述性轉(zhuǎn)移娃豹。本質(zhì)上是通過表述完成資源的轉(zhuǎn)移

1.2 RESTful的結(jié)構(gòu)购裙?

RESTful的核心思想就是:客戶端發(fā)出的數(shù)據(jù)操作指令都是“動(dòng)詞+賓語(yǔ)”的結(jié)構(gòu)懂版。例如GET /articles這個(gè)命令,GET是動(dòng)詞躏率,/articles是賓語(yǔ)躯畴。

需要注意的是:根據(jù)HTTP規(guī)范民鼓,動(dòng)詞一律大寫。

動(dòng)詞通常來說蓬抄,其實(shí)就是五種HTTP方法丰嘉,對(duì)應(yīng)CRUD操作。

動(dòng)詞 操作
GET 讀取
POST 新建
PUT 更新
PATCH 部分更新
DELETE 刪除

作為設(shè)計(jì)基礎(chǔ)嚷缭,還是需要遵循幾個(gè)原則的:

  1. 當(dāng)標(biāo)準(zhǔn)合理的時(shí)候遵守標(biāo)準(zhǔn)饮亏。
  2. API應(yīng)該對(duì)程序員友好,并且在瀏覽器地址容易輸入峭状。
  3. API應(yīng)該簡(jiǎn)單克滴,直觀,容易使用的同時(shí)優(yōu)雅优床。
  4. API應(yīng)該具有足夠的靈活性來支持上層ui劝赔。
  5. API設(shè)計(jì)權(quán)衡上述幾個(gè)原則。
  • GET /tickets #獲取ticket列表胆敞;
  • GET /tickets/12 #查看某個(gè)具體的ticket着帽;
  • POST /tickets #新建一個(gè)ticket;
  • PUT /tickets/12 #更新ticket 12移层;
  • DELETE /tickets/12 #刪除ticket 12仍翰;

顯然從API用戶的角度來看,“資源”應(yīng)該是一個(gè)名詞观话。即使在內(nèi)存數(shù)據(jù)結(jié)構(gòu)模型和資源已經(jīng)有了很好的對(duì)應(yīng)予借,API設(shè)計(jì)的時(shí)候仍然不需要把它們一對(duì)一的暴露出來,這里的關(guān)鍵是隱藏內(nèi)部資源频蛔,暴露必須的對(duì)外資源灵迫。

2. 如何書寫RESTful

2.1 動(dòng)詞的覆蓋

有些客戶端只能使用GETPOST這兩種方法,服務(wù)器必須接受POST模擬其他三個(gè)方法(PUT/PATCH/DELETE)晦溪。

這時(shí)瀑粥,客戶端發(fā)出的HTTP請(qǐng)求,需要加上X-HTTP-Method-Override屬性三圆,告訴服務(wù)器應(yīng)該使用哪種動(dòng)詞狞换,覆蓋POST方法。

POST /api/Person/4 HTTP/1.1  
X-HTTP-Method-Override: PUT

上面代碼中舟肉,X-HTTP-Method-Override指定本次請(qǐng)求的方法是PUT修噪,而不是POST。

2.1 賓語(yǔ)必須是名詞

賓語(yǔ)就是API的URL路媚,是Http動(dòng)詞作用的對(duì)象割按,他表述的是一個(gè)資源。應(yīng)該是名詞磷籍,不應(yīng)該是動(dòng)詞适荣。

!T毫臁弛矛!Restful反例

/getAllCars
/createNewCar
/deleteAllRedCars

2.2 賓語(yǔ)是單數(shù)還是復(fù)數(shù)

既然URL是名詞,那么應(yīng)該使用復(fù)數(shù)比然,還是單數(shù)丈氓?

這里沒有統(tǒng)一的規(guī)定,但是常見的操作是讀取一個(gè)集合强法,比如GET /articles(讀取所有的文章)這里明顯是復(fù)數(shù)万俗。

為了統(tǒng)一起見,建議都使用復(fù)數(shù)URL饮怯,比如GET /articles/2要好于GET /article/2闰歪。

2.3 多級(jí)的URL的寫法

按照Rails中標(biāo)準(zhǔn)定義的方式:

  1. 若定義這個(gè)資源的兩個(gè)參數(shù)具有從屬關(guān)系,那么生成的url就是owner/1/property/1蓖墅,其中property從屬于owner库倘。比如用戶1的編號(hào)為2的文章,就是users/1/articles/2论矾。
  2. 如果兩個(gè)資源是平等的教翩,那么一般是作為URL中HTTP方法的參數(shù)。

舉個(gè)小栗子

比如匯款動(dòng)作贪壳,從賬戶1向賬戶2匯款500元饱亿。如何設(shè)計(jì)URL?
小優(yōu)同學(xué):POST /accounts/1/transfer/500/to/2闰靴;
小胖老師:答錯(cuò)了彪笼,請(qǐng)坐下。
正確的應(yīng)該是:將動(dòng)詞轉(zhuǎn)換為名稱传黄,(只是一個(gè)匯款操作)
即:POST /accounts/transaction?from=1&to=2&amount=500.00杰扫;

3. 狀態(tài)碼

客戶端的每一次請(qǐng)求,服務(wù)器都必須給出回應(yīng)膘掰≌滦眨回應(yīng)包括HTTP狀態(tài)碼和數(shù)據(jù)兩部分。

狀態(tài)碼 相關(guān)操作
1xx 相關(guān)信息
2xx 操作成功
3xx 重定向
4xx 客戶端錯(cuò)誤
5xx 服務(wù)器錯(cuò)誤

這五大類共包含了100多種狀態(tài)碼识埋,覆蓋了絕大部分可能的情況凡伊。每一種狀態(tài)碼都有標(biāo)準(zhǔn)(或者是約定)解釋,客戶端只需要查看狀態(tài)碼窒舟,就可以判斷出發(fā)生了什么情況系忙,所以服務(wù)器應(yīng)返回盡可能精確的1狀態(tài)碼。

API不需要1xx狀態(tài)碼惠豺,下面介紹其他四類狀態(tài)碼的精確含義银还。

3.1 2xx狀態(tài)碼

雖然200狀態(tài)碼表示操作成功风宁,但是不同的方法可以返回更精確的狀態(tài)碼。

HTTP操作 狀態(tài)碼
GET 200 ok
POST 201 created
PUT 200 ok
PATCH 200 ok
DELETE 204 no content
  • POST返回201狀態(tài)碼蛹疯,表示生成了新的資源戒财;

  • DELETE返回204狀態(tài)碼,表示資源已經(jīng)不存在捺弦;

  • 202 Accepted狀態(tài)碼表示服務(wù)器已經(jīng)收到請(qǐng)求饮寞,但還未進(jìn)行處理,會(huì)在未來再處理列吼,通常用于異步操作幽崩。

HTTP/1.1 202 Accepted

{
  "task": {
    "href": "/api/company/job-management/jobs/2130040",
    "id": "2130040"
  }
}

3.2 3xx狀態(tài)碼

API用不到301狀態(tài)碼(永久重定向)和302狀態(tài)碼(暫時(shí)重定向,307也是這個(gè)含義)寞钥,因?yàn)樗鼈兛捎蓱?yīng)用級(jí)別返回慌申,瀏覽器會(huì)直接跳轉(zhuǎn),API級(jí)別可以不考慮這兩種情況凑耻。

API用到的3xx狀態(tài)碼太示,主要是303 See Other,表示參考另一個(gè)URL香浩。它與302和307含義一樣类缤,也是“暫時(shí)重定向”,區(qū)別在于302和307用于GET請(qǐng)求邻吭,而303用于POST餐弱、PUT和DELETE請(qǐng)求。收到303以后囱晴,瀏覽器不會(huì)自動(dòng)跳轉(zhuǎn)膏蚓,會(huì)讓用戶自己決定下一步怎么辦,下面是一個(gè)例子畸写。

HTTP/1.1 303 See Other
Location: /api/orders/12345

3.3 4xx狀態(tài)碼

4xx狀態(tài)碼表示客戶端錯(cuò)誤驮瞧,主要有下面幾種。

狀態(tài)碼 含義
400 Bad Request 服務(wù)器不理解客戶端請(qǐng)求枯芬,未做任何處理
401 Unauthorized 用戶未提供身份驗(yàn)證憑證论笔,或者沒有通過身份驗(yàn)證
403 Forbidden 用戶通過身份驗(yàn)證,但沒有權(quán)限訪問請(qǐng)求資源
404 Not Found 所請(qǐng)求資源不存在千所,或不可用
405 Method Not Allowed 用戶已經(jīng)通過身份驗(yàn)證狂魔,但是所用HTTP方法不在權(quán)限內(nèi)
410 Gone 所請(qǐng)求資源已經(jīng)從這個(gè)地址轉(zhuǎn)移,不可再用
415 Unsupported Media Type 客戶端要求返回格式不支持淫痰。比如API只能返回JSON最楷,但Client要求返回XML
422 Unprocessable Entity 客戶端上傳附件無(wú)法處理,導(dǎo)致請(qǐng)求失敗
429 Too Many Request 客戶端的請(qǐng)求次數(shù)超過限額

3.4 5xx狀態(tài)碼

5xx狀態(tài)碼表示服務(wù)端錯(cuò)誤,一般來說籽孙,API不會(huì)像用戶透露服務(wù)器的詳細(xì)信息烈评,所以只要兩個(gè)狀態(tài)碼就夠了。

狀態(tài)碼 含義
500 Internal Server Error 客戶端請(qǐng)求有效蚯撩,服務(wù)器處理時(shí)發(fā)生了意外
503 Service Unavailable 客戶端無(wú)法處理請(qǐng)求础倍,一般用于網(wǎng)站維護(hù)狀態(tài)

4. 服務(wù)器回應(yīng)

4.1 不要返回純文本

API返回的數(shù)據(jù)格式,不應(yīng)該是純文本胎挎,而應(yīng)該是一個(gè)JSON對(duì)象,因?yàn)檫@樣才能返回標(biāo)準(zhǔn)的結(jié)構(gòu)化數(shù)據(jù)忆家。所以客戶端回應(yīng)的HTTP頭的Content-Type屬性要設(shè)為application/json犹菇。

客戶端請(qǐng)求時(shí),也要明確告訴服務(wù)器芽卿,可以接受JSON格式揭芍,即請(qǐng)求的HTTP頭的ACCEPT屬性也要設(shè)為application/json

GET /orders/2 HTTP/1.1 
Accept: application/json

4.2 發(fā)生錯(cuò)誤時(shí)卸例,不要返回200錯(cuò)誤碼

有一種不恰當(dāng)?shù)淖龇ㄊ浅蒲睿词拱l(fā)生錯(cuò)誤,也返回200狀態(tài)碼筷转,把錯(cuò)誤信息放在數(shù)據(jù)體里面姑原,就像下面這種:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "status": "failure",
  "data": {
    "error": "Expected at least two items in list."
  }
}

上面代碼,解析數(shù)據(jù)體以后呜舒,才能得知操作失敗锭汛。
這種做法實(shí)際上是取消了狀態(tài)碼,這是完全不可取的袭蝗。正確的做法是:狀態(tài)碼反映發(fā)生的錯(cuò)誤唤殴,具體的錯(cuò)誤信息放在數(shù)據(jù)體里面返回。

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "Invalid payoad.",
  "detail": {
     "surname": "This field is required."
  }
}

4.3 提供鏈接

HATEOAS怎么讀(Hypermedia as the engine of application state)超媒體作為應(yīng)用狀態(tài)引擎到腥《涫牛【“小胖哥哥,你英語(yǔ)翻譯太棒了”——小優(yōu)】

我們知道REST是使用標(biāo)準(zhǔn)的HTTP方法來操作資源的乡范。但僅僅因此就理解成帶CURD的WEB數(shù)據(jù)庫(kù)架構(gòu)就太low了吧配名。這種說法忽略了一個(gè)核心的概念,即“超媒體即應(yīng)用狀態(tài)引擎(Hypermedia as the engine of application state)”篓足。

超媒體是什么段誊?

當(dāng)你瀏覽Web頁(yè)面的時(shí)候,從一個(gè)連接跳到一個(gè)頁(yè)面栈拖,再?gòu)牧硪粋€(gè)連接跳到另外一個(gè)頁(yè)面连舍,就是利用超媒體的概念:把一個(gè)個(gè)資源鏈接起來。

要達(dá)到這個(gè)目的,就要求在表述表格里面加入鏈接來引導(dǎo)客戶端索赏,在《RESTFul Web Services》一書中盼玄,作者把這種具有鏈接的特性稱為“連通性”

RESTful API最好做到HATEOAS潜腻,即返回結(jié)果中提供鏈接埃儿,連向其他API方法,使得用戶不用查詢文檔融涣,也知道下一步怎么做童番。比如,用戶向api.example.com的根路徑發(fā)出請(qǐng)求威鹿,會(huì)得到這樣一個(gè)文檔剃斧。

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

上面代碼表示,文檔中有一個(gè)link屬性忽你,用戶讀取這個(gè)屬性就知道下一步調(diào)用什么API幼东,rel表示這個(gè)API與當(dāng)前網(wǎng)址的關(guān)系(collection關(guān)系,并給出該collection的網(wǎng)址)科雳,href表示API的路徑根蟹,title表示API的標(biāo)題,type表示返回類型糟秘。

Hypermedia API的設(shè)計(jì)被稱為HATEOAS简逮。GIThub的API就是這種設(shè)計(jì),訪問api.github.com就會(huì)得到一個(gè)所有可用API的網(wǎng)址列表蚌堵。

HATEOAS實(shí)踐

那我們就去訪問訪問https://api.github.com/user這個(gè)地址吧买决。

訪問api.github.com/user

參考文章:
restful 接口命名規(guī)則

RESTful API 最佳實(shí)踐

不要被名字嚇到-RESTful、HATEOAS吼畏、Spring boot之整合

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末督赤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泻蚊,更是在濱河造成了極大的恐慌躲舌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件性雄,死亡現(xiàn)場(chǎng)離奇詭異没卸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秒旋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門约计,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迁筛,你說我怎么就攤上這事煤蚌。” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵尉桩,是天一觀的道長(zhǎng)筒占。 經(jīng)常有香客問我,道長(zhǎng)蜘犁,這世上最難降的妖魔是什么翰苫? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮这橙,結(jié)果婚禮上奏窑,老公的妹妹穿的比我還像新娘。我一直安慰自己屈扎,他們只是感情好良哲,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著助隧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滑沧。 梳的紋絲不亂的頭發(fā)上并村,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音滓技,去河邊找鬼哩牍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛令漂,可吹牛的內(nèi)容都是我干的膝昆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼叠必,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼荚孵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纬朝,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤收叶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后共苛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體判没,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年隅茎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澄峰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辟犀,死狀恐怖俏竞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤胞此,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布臣咖,位于F島的核電站,受9級(jí)特大地震影響漱牵,放射性物質(zhì)發(fā)生泄漏夺蛇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一酣胀、第九天 我趴在偏房一處隱蔽的房頂上張望刁赦。 院中可真熱鬧,春花似錦闻镶、人聲如沸甚脉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)牺氨。三九已至,卻和暖如春墩剖,著一層夾襖步出監(jiān)牢的瞬間猴凹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工岭皂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留郊霎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓爷绘,卻偏偏與公主長(zhǎng)得像书劝,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子土至,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容