本文已收錄至 https://github.com/yessimida/yes ,這裡有我的所有文章分類彙總,歡迎 star!
RESTful 想必大家都耳熟能詳。
但是為什麼要有 RESTful,RESTful 到底是什麼意思。
為什麼稱之為 RESTful 架構?
我不用 RESTful 不行嗎?
什麼樣才叫真正的 RESTful ?
其實網上 RESTful 的文章有挺多的,不過有些講的糊里糊塗的,而且很大部分都忽略了 HATEOAS。
在之前的面試中面試官就問過我,你怎麼理解 RESTful 的,英文全稱是啥?為什麼叫這個名字?
當時我人都傻了。
面試官不講武德,針對我這個剛出社會的小夥子。
其實有很多人也稀裡糊塗的,也包括我自己。
就面向資源唄,不加動詞咯,還能咋滴,我加動詞不也能用嗎?
而且我之前還特不能理解,為啥這叫架構?
我特意搜尋了下架構的解釋。
軟體架構是有關軟體整體結構與元件的抽象描述,用於指導大型軟體系統各個方面的設計。
整體結構與元件的抽象描述。
RESTful 哪有什麼元件和結構之間的玩意?
所以就至今我寫下這篇文章的時候我也理解不了為什麼叫 RESTful 架構。
可能是我對架構的理解太狹隘,還不到火候。
我個人只能理解成 RESTful 風格的 API 設計,也就是說 RESTful 只是一種指導風格,就像我們 Java 要用駝峰命名法。
那不用駝峰命名法程式碼就不能跑了嗎?
當然能跑,這只是一種希望大家都能遵循的規範。
對 RESTful 而言我覺得算不上規範,只能說指導風格。
來讓我們正式的進入對 RESTful 的剖析。
REST
REST 不是一個單詞,是 Representational State Transfer 的縮寫。
直譯過來就是表述性狀態轉移。
我對這個名字蒙了一年多,就不能說點能聽得懂的嘛。
從提出 REST 的論文中我翻了翻,沒有明說但是表達的意思是其實它還有個主語 Resource 。
所以是資源的表述性狀態轉移。
稍微可以理解一點了。
我們先不管什麼狀態轉移,大致先有點感覺。
知道 REST 之後 RESTful 就不難解釋了,加 ful 就是變形容詞了,比如 wonderful girl。
至此對名字稍微解釋了一下,疑惑還在沒事,我們們慢慢理。
REST 的核心
核心就是資源,用 URL 定位資源,用 HTTP 動詞來描述所要做的操作。
HTTP的提供了很多動詞:GET、PUT、POST、DELETE......
這些動詞都是有含義的。
比如 GET 就是獲取資源,是查詢請求。
PUT 指的是修改資源,是冪等的。
POST 也是修改(新增也是一種修改),指的是不冪等的操作。
所以根據這些規範我們都能得知這次互動的一些動作,所以正確的使用姿勢如下:
比如獲取一個 user。
錯誤姿勢:GET /getUserById?userId=1
。
正確姿勢:GET /users/1
。
再比如新增 user。
錯誤姿勢:POST /addUser
(省略body)。
正確姿勢:POST /users
(省略body)。
可以看到 HTTP 的動詞其實就能指代你要對資源做的操作,所以不需要在 URL 上做一些東西,就把 URL 表明的東西就看做一個資源即可。
這裡注意要用對 HTTP 動詞,比如一個獲取資源的請求用 PUT,用了也能獲取資源但是這不合適。
其實更深一步的理解是 HTTP 是一個協議。
協議其實就是約定好的一個東西,協議就規定 GET 是獲取資源,那你非得在 URL 上再重複一遍或者所有請求不論增刪改都用 GET 這個動作,這其實就是沒有完全遵循這個協議。
可以說只是把 HTTP 當成一個傳輸管道,而不是約定好的協議。
這其實是對 HTTP 更深一層的認識,我認為也是 RESTful 被推出的原因。
當然理想很豐滿,現實很骨感,還是有很多人就 getUserById
。
不過我個人覺得問題不大,公司統一就行。
HATEOAS
即 Hypermedia as the Engine of Application State 的縮寫,翻譯過來就是作為應用狀態引擎的超媒體。
這也是 REST 提出的設計。
是不是理解不了?其實很簡單。
例子我就不自己編了,抄一下 stackoverflow 回答上的例子。
比如你請求獲取使用者列表:
GET /users
Accept: application/json+userdb
此時的返回應該是:
200 OK
Content-Type: application/json+userdb
{
"users": [
{
"id": 1,
"name": "Emil",
"country: "Sweden",
"links": [
{
"href": "/user/1",
"rel": "self",
"method": "GET"
},
{
"href": "/user/1",
"rel": "edit",
"method": "PUT"
},
{
"href": "/user/1",
"rel": "delete",
"method": "DELETE"
}
]
},
{
"id": 2,
....省略.....
}
],
"links": [
{
"href": "/user",
"rel": "create",
"method": "POST"
}
]
}
重點就是這個 links,結果會返回你能對這個資源所做的操作。
比如對於 userId 是 1 的,你呼叫 PUT /user/1
就是做修改這個使用者,DELETE /user/1
就是刪除這個使用者。
最外層的 links 告訴你用 POST /user
就能再建立一個使用者。
這裡還有個隱藏資訊,可能看到外層的 links 沒有返回 DELETE 的資訊,說明此時客戶端無法刪除使用者!
所以說 RESTful API 還需要在返回此時能做資源所做的操作,這樣客戶端就知道它能做什麼。
它也不需要管具體怎麼做,反正返回裡面會告訴它 DELETE 就這樣這樣,POST 就這樣這樣。
沒告訴它的就是不能做的。
然後這個時候再去理解下資源的表述性狀態轉移,是不是感覺來了?
如果說上一 part 提到用 HTTP 的動詞來指代動作, URL 僅表示資源的現實是骨感的。
那麼 HATEOAS 的現實就是灰。
基本上沒幾家公司會這麼做。
就我個人而言這玩意沒啥用。
它的出發點是讓客戶端從響應就能得知對資源操作的入口,並且通過響應就得知哪些動作能執行。
聽起來好像有點用,但是就我目前的功力,我只能看到響應變得十分冗餘。
最後
這篇文章關於 RESTful API 具體的寫法我就提到一些,還有挺多的就自己查資料吧。
文章的目的是為了讓你理解 RESTful API,我再總結一下重點。
HTTP 是協議,不是傳輸通道。(對協議不理解的看我之前的 HTTP 分析)
所以協議約定了很多東西,推薦我們按照協議的用法進行客戶端和服務端的互動。
也就是 RESTful 表明的面向資源,通過 HTTP 動作 + URL 上的資源。
RESTful 還提到了 HATEOAS,雖說基本上沒什麼公司會這樣使用,但是它能讓你更好的理解 REST 這個名字的含義。
RESTful 是一種風格,你是否採用這種風格對你的程式執行沒有影響,類比駝峰命名來思考。
簡而言之,就是不要在 URL 上表現出動作,用 HTTP 動詞代表動作,URL 上只做資源,僅此而已。
至於要不要嚴格遵循 RESTful 風格,我個人的看法是公司內部保持一致就行。
歡迎加我好友進行深入地交流,備註「進群」,拉你進交流&內推群。
平日的面試題遇到難處,或者看某個知識點翻遍全網的資料還是感覺很模糊、不透徹,可以私聊我,給我留言。
遇到合適的我會整理寫出一篇文章,注意這個前提我認為合適的。
那種工作遇到很細節的場景的還是別了,這種問你上司比較合適:)。
巨人的肩膀
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2
http://www.ruanyifeng.com/blog/2011/09/restful.html
https://stackoverflow.com/questions/671118/what-exactly-is-restful-programming/3950863#3950863
https://en.wikipedia.org/wiki/HATEOAS
更多硬核文章等你來讀。
微信搜尋【yes的練級攻略】,關注 yes,回覆【123】一份20W字的演算法刷題筆記等你來領,從一點點到億點點,我們下篇見。