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è)原則的:
- 當(dāng)標(biāo)準(zhǔn)合理的時(shí)候遵守標(biāo)準(zhǔn)饮亏。
- API應(yīng)該對(duì)程序員友好,并且在瀏覽器地址容易輸入峭状。
- API應(yīng)該簡(jiǎn)單克滴,直觀,容易使用的同時(shí)優(yōu)雅优床。
- API應(yīng)該具有足夠的靈活性來支持上層ui劝赔。
- 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)詞的覆蓋
有些客戶端只能使用GET
和POST
這兩種方法,服務(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)定義的方式:
- 若定義這個(gè)資源的兩個(gè)參數(shù)具有從屬關(guān)系,那么生成的url就是
owner/1/property/1
蓖墅,其中property從屬于owner库倘。比如用戶1的編號(hào)為2的文章,就是users/1/articles/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)址列表蚌堵。
那我們就去訪問訪問https://api.github.com/user這個(gè)地址吧买决。
參考文章:
restful 接口命名規(guī)則