国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

詳解REST架構(gòu)風(fēng)格

ChanceWong / 692人閱讀

摘要:但是遠(yuǎn)遠(yuǎn)不僅是指的風(fēng)格,它是一種網(wǎng)絡(luò)應(yīng)用的架構(gòu)風(fēng)格。參考用定位資源在架構(gòu)風(fēng)格中,用來指定一個(gè)資源。完整狀態(tài)碼列表如何設(shè)計(jì)在過去不使用架構(gòu)風(fēng)格的時(shí)候,如果我們要設(shè)計(jì)一個(gè)系統(tǒng),會(huì)以操作為出發(fā)點(diǎn),然后圍繞它去建設(shè)其他需要的東西。

引言

作為Web開發(fā)者,你可能或多或少了解一些REST的知識(shí),甚至已經(jīng)非常習(xí)慣于它,以至于在正式地學(xué)習(xí)REST的時(shí)候,你可能心里會(huì)想:“本來就是這樣做的啊,不然還能怎么做呢?”
確實(shí)是這樣,REST已經(jīng)成為Web世界的一種內(nèi)在架構(gòu)原則。這主要是因?yàn)?strong>REST的產(chǎn)生確實(shí)與HTTP有著密不可分的聯(lián)系。REST的提出者Roy Fielding在Web界是一位舉足輕重的人物,他是HTTP協(xié)議(1.0版和1.1版)的主要設(shè)計(jì)者、Apache服務(wù)器軟件的作者之一、Apache基金會(huì)的第一任主席……Fielding在幾年以后回顧起REST的設(shè)計(jì)過程時(shí),他說道:

Throughout the HTTP standardization process, I was called on to defend the design choices of the Web. That is an extremely difficult thing to do within a process that accepts proposals from anyone on a topic that was rapidly becoming the center of an entire industry. I had comments from well over 500 developers, many of whom were distinguished engineers with decades of experience, and I had to explain everything from the most abstract notions of Web interaction to the finest details of HTTP syntax. That process honed my model down to a core set of principles, properties, and constraints that are now called REST.

在HTTP標(biāo)準(zhǔn)化的過程中,F(xiàn)ielding作為作者之一,負(fù)責(zé)向外界對(duì)HTTP的設(shè)計(jì)作出解釋和辯護(hù)。在這個(gè)過程中,他的思維模型受到不斷地錘煉,一套準(zhǔn)則從中沉淀了下來,這就是REST。

本篇文章的寫作目的是,與讀者一起了解REST的內(nèi)在,認(rèn)識(shí)REST的優(yōu)勢(shì),而不再將它當(dāng)作是“理所當(dāng)然”。

REST

REST是Representational State Transfer(在表示層上的狀態(tài)傳輸)的縮寫,這個(gè)詞的字面意思要在文章的后面才能解釋清楚。REST是一種WEB應(yīng)用的架構(gòu)風(fēng)格,它被定義為6個(gè)限制,滿足這6個(gè)限制,能夠獲得諸多優(yōu)勢(shì)(詳細(xì)優(yōu)點(diǎn)在文章最后總結(jié))。

先用一句話來概括RESTful API(具有REST風(fēng)格的API): 用URL定位資源,用HTTP動(dòng)詞(GET,HEAD,POST,PUT,PATCH,DELETE)描述操作,用響應(yīng)狀態(tài)碼表示操作結(jié)果。

但是REST遠(yuǎn)遠(yuǎn)不僅是指API的風(fēng)格,它是一種網(wǎng)絡(luò)應(yīng)用的架構(gòu)風(fēng)格。我們到后面會(huì)有所體會(huì)。
另外,需要注意的是,REST的原則不僅僅適用于HTTP協(xié)議。但是,由于REST的應(yīng)用場(chǎng)景絕大部分是WEB應(yīng)用,本篇文章將基于HTTP來討論REST。

引入:從另一個(gè)角度看待前后端分離

我們?yōu)g覽一個(gè)網(wǎng)站,說到底就是與這個(gè)網(wǎng)站中的資源進(jìn)行互動(dòng)(獲取、提交、更新、刪除)。前端的工作,就是為用戶從服務(wù)端獲取資源、展示資源、請(qǐng)求服務(wù)端改變資源。

RESTful API有助于客戶端和服務(wù)端的功能分離,服務(wù)器完全扮演著一個(gè)“資源服務(wù)商”的角色。各種不同的客戶端都可以通過一致的API與這個(gè)“資源服務(wù)商”交流,從而與資源進(jìn)行互動(dòng)。

資源

在REST架構(gòu)中,“資源”扮演者主要角色。它具有以下特點(diǎn):

資源是任何可以操作(獲取、提交、更新、刪除)的數(shù)據(jù),比如一個(gè)文檔(document)、一張圖片……

wikipedia: "Web resources" were first defined on the World Wide Web as documents or files identified by their URLs. However, today they have a much more generic and abstract definition that encompasses every thing or entity that can be identified, named, addressed, or handled, in any way whatsoever, on the web. “資源”包括Web中任何可以被標(biāo)識(shí)、命名、定位、處理的事物。

資源的集合也是一種資源,比如blogs表示博客(資源)的集合。

進(jìn)行資源操作的時(shí)候,用URI來指定被操作的資源。如果一個(gè)URI不僅能標(biāo)識(shí)一個(gè)網(wǎng)絡(luò)上的資源,還能夠定位這個(gè)資源,那么這個(gè)URI也叫URL。

資源是一個(gè)抽象的概念,資源無法被傳輸,只能傳輸資源的表示(representation)。一個(gè)資源可以有多種表示,比如,一個(gè)資源可以用HTML、XML、JSON來表示。具體傳輸哪種表示取決于服務(wù)端的能力和客戶端的要求。傳輸?shù)谋硎疚幢鼐褪欠?wù)器存儲(chǔ)時(shí)使用的表示,比如,這個(gè)資源在服務(wù)器不是以HTML或XML或JSON來存儲(chǔ)的,可能是一種更加利于壓縮的表示。總的來說,“表示”是“資源”的存儲(chǔ)和傳輸形式,“資源”是“表示”的內(nèi)容(抽象概念)。不管用什么形式來表示,始終描述的是這個(gè)資源。

舉一個(gè)例子,當(dāng)我們討論“文章列表”這個(gè)資源時(shí),我們并不在乎它是json格式還是xml格式,我們指的是它的含義:某個(gè)用戶的所有文章。但是當(dāng)我們真的要在服務(wù)器與客戶端之間傳輸數(shù)據(jù)的時(shí)候,不能直接“傳輸資源”,因?yàn)橘Y源太抽象了,發(fā)送方必須要以某一種表示(representation)來傳遞它(比如json),接收方才能很好地解析和處理。

表示(representation)包括數(shù)據(jù)(data,表示資源本身)和元數(shù)據(jù)(metadata,用于描述這個(gè)representation)。在Roy Fielding的論文中有這個(gè)定義:A representation is a sequence of bytes, plus representation metadata to describe those bytes.

在前面的例子中,嚴(yán)格來說,“json字符串”并不是完整的representation,整個(gè)HTTP響應(yīng)才是representation。HTTP body中的是數(shù)據(jù),HTTP header中的是元數(shù)據(jù)(尤其是Content-Type這種字段)。

參考 https://restfulapi.net/
用URL定位資源

在RESTful架構(gòu)風(fēng)格中,URL用來指定一個(gè)資源。資源就是服務(wù)器上可操作的實(shí)體(可以理解為數(shù)據(jù))。比如說URL/api/users表示的是該網(wǎng)站的所有用戶,這是一種資源,可以與之互動(dòng)(獲取、提交、更新、刪除)。另外,資源地址具有層次結(jié)構(gòu),比如/api/users/csr表示用戶名為"csr"的用戶,/api/users/csr/blogs表示"csr"的所有博客,/api/users/csr/blogs/1234567表示其中的某一篇博客。這些都是資源,后者嵌套在前者之中。

既然URL表示一個(gè)資源,自然就不應(yīng)該包含動(dòng)詞,它應(yīng)該由名詞組成。一個(gè) not RESTful 的例子是通過向api/delete/resource發(fā)送GET請(qǐng)求來刪除一個(gè)資源。

更詳細(xì)的URL設(shè)計(jì)可以查看阮一峰的"RESTful API 設(shè)計(jì)指南"或者知乎高票回答。URL風(fēng)格只是REST的外表,不是本文的重點(diǎn)。
操作資源

既然通過URL能夠指定一個(gè)服務(wù)器上的資源。那么我們應(yīng)該如何與這個(gè)資源進(jìn)行互動(dòng)呢?我們對(duì)這個(gè)資源(URL)使用不同的HTTP方法,就代表對(duì)這個(gè)資源的不同操作:

GET(SELECT):從服務(wù)器獲取資源(一個(gè)資源或資源集合)。

POST(CREATE):在服務(wù)器新建一個(gè)資源(也可以用于更新資源)。

PUT(UPDATE):在服務(wù)器更新資源(客戶端提供改變后的完整資源)。

PATCH(UPDATE):在服務(wù)器更新資源(客戶端提供改變的部分)。

DELETE(DELETE):從服務(wù)器刪除資源。

HEAD:獲取資源的元數(shù)據(jù)。

OPTIONS:獲取信息,關(guān)于資源的哪些屬性是客戶端可以改變的。

GET、HEAD、PUT、DELETE方法是冪等方法(對(duì)于同一個(gè)內(nèi)容的請(qǐng)求,發(fā)出n次的效果與發(fā)出1次的效果相同)。
GET、HEAD方法是安全方法(不會(huì)造成服務(wù)器上資源的改變)。

PATCH不一定是冪等的。PATCH的實(shí)現(xiàn)方式有可能是"提供一個(gè)用來替換的數(shù)據(jù)",也有可能是"提供一個(gè)更新數(shù)據(jù)的方法"(比如data++)。如果是后者,那么PATCH不是冪等的。
Method 安全性 冪等性
GET
HEAD
POST × ×
PUT ×
PATCH × ×
DELETE ×
參考:HTTP Methods for RESTful Services
通過HTTP狀態(tài)碼表示操作的結(jié)果

雖然HTTP狀態(tài)碼設(shè)計(jì)的本意就是表示操作結(jié)果,但是有時(shí)候人們往往沒有很好的利用它,RESTful API要求充分利用HTTP狀態(tài)碼

200 OK - [GET]:服務(wù)器成功返回用戶請(qǐng)求的數(shù)據(jù),該操作是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功。
202 Accepted - [*]:表示一個(gè)請(qǐng)求已經(jīng)進(jìn)入后臺(tái)排隊(duì)(異步任務(wù))
204 NO CONTENT - [DELETE]:用戶刪除數(shù)據(jù)成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請(qǐng)求有錯(cuò)誤,服務(wù)器沒有進(jìn)行新建或修改數(shù)據(jù)的操作,該操作是冪等的。
401 Unauthorized - [*]:表示用戶沒有權(quán)限(令牌、用戶名、密碼錯(cuò)誤)。
403 Forbidden - [*] 表示用戶得到授權(quán)(與401錯(cuò)誤相對(duì)),但是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發(fā)出的請(qǐng)求針對(duì)的是不存在的記錄,服務(wù)器沒有進(jìn)行操作,該操作是冪等的。
406 Not Acceptable - [GET]:用戶請(qǐng)求的格式不可得(比如用戶請(qǐng)求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用戶請(qǐng)求的資源被永久刪除,且不會(huì)再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),發(fā)生一個(gè)驗(yàn)證錯(cuò)誤。
500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯(cuò)誤,用戶將無法判斷發(fā)出的請(qǐng)求是否成功。
完整狀態(tài)碼列表
如何設(shè)計(jì)RESTful API

在過去不使用RESTful架構(gòu)風(fēng)格的時(shí)候,如果我們要設(shè)計(jì)一個(gè)系統(tǒng),會(huì)以“操作”為出發(fā)點(diǎn),然后圍繞它去建設(shè)其他需要的東西。
舉個(gè)例子,我們要向系統(tǒng)中增加一個(gè)用戶登陸的功能:

需要一個(gè)用戶登陸的功能(操作)

約定一個(gè)用于登錄的API(也就是URL)

約定這個(gè)API的使用方式(發(fā)送響應(yīng)什么數(shù)據(jù)、格式是什么)

前后端針對(duì)這個(gè)API進(jìn)行開發(fā)

這種設(shè)計(jì)方式有如下缺點(diǎn):

當(dāng)我們不斷為這個(gè)系統(tǒng)增加操作,每增加一個(gè)操作都要按照上面的流程設(shè)計(jì)一次,第2和3點(diǎn)的工作實(shí)際是可以大大削減的(通過REST)。

操作之間可能是有依賴的,依賴多起來,系統(tǒng)會(huì)變得很復(fù)雜。

我們的API缺乏一致性(需要一份龐大的文檔來記錄api的地址、使用方式)。

操作通常被認(rèn)為是有副作用(Side Effect)的,很難使用緩存技術(shù)。

而如果我們?cè)O(shè)計(jì)REST風(fēng)格的系統(tǒng),資源是第一位的考慮,首先從資源的角度進(jìn)行系統(tǒng)的拆分、設(shè)計(jì),而不是像以往一樣以操作為角度來進(jìn)行設(shè)計(jì)。

用兩個(gè)例子來說明:銀行的轉(zhuǎn)賬API,即時(shí)通訊軟件中發(fā)送消息的API。

這兩個(gè)功能非常具有“動(dòng)作性”,看起來和“資源”聯(lián)系不大,很容易就會(huì)設(shè)計(jì)成not RESTful的API:POST /transfer/${amount}/to/${toUserID}POST /api/sendMessage
一旦在URL中引入了動(dòng)詞,這個(gè)URL的功能就定死了,無法用于別的用途(比如,GET /transfer/${amount}/to/${toUserID}GET /api/sendMessage的語義很奇怪,不好使用)。并且,不同功能的API有各自的結(jié)構(gòu),一致性很差,需要一份詳細(xì)的API文檔才能使用。

這種情況下,要如何通過RESTful架構(gòu)風(fēng)格,設(shè)計(jì)一套一致、多用途的URL呢?
簡(jiǎn)單地說,就是將一個(gè)“動(dòng)作”理解為“操作一個(gè)資源”。這里的“操作”是指HTTP的方法。

對(duì)于轉(zhuǎn)賬動(dòng)作,就可以理解為“新建一個(gè)轉(zhuǎn)賬事務(wù)”(轉(zhuǎn)賬事務(wù)是資源),因此API就可以設(shè)置成這樣: POST /transactions,請(qǐng)求體為:to=632&amount=500。這樣的設(shè)計(jì)不但簡(jiǎn)潔明了,而且我們可以將這個(gè)URL用于別的用途:通過GET /transactions來獲取該用戶的所有轉(zhuǎn)賬事務(wù)。還可以將GET /transactions/456828定義為“獲取某一次轉(zhuǎn)賬記錄”。

即時(shí)通訊軟件中發(fā)送消息的動(dòng)作,我們可以理解為“操作聊天記錄(聊天記錄是資源,它是由“消息”組成的集合,消息也是資源)”,所以API設(shè)計(jì)為

POST /messages # 創(chuàng)建新的聊天記錄(body傳輸消息的內(nèi)容)
GET /messages # 獲取聊天記錄(返回一個(gè)數(shù)組,其中每個(gè)項(xiàng)是一個(gè)消息)
GET /messages/${messageID} # 獲取某個(gè)消息的詳細(xì)信息
PUT /messages/${messageID} # 更新某個(gè)消息(body傳輸消息的內(nèi)容)
DELETE /messages/${messageID} # 刪除某個(gè)消息的記錄
同理,論壇類應(yīng)用發(fā)帖、回帖的API也可以這樣設(shè)計(jì)。

從以上的兩個(gè)例子我們可以看出,使用RESTful風(fēng)格可以克服傳統(tǒng)架構(gòu)風(fēng)格的那4個(gè)缺陷:

設(shè)計(jì)API工作量減少,因?yàn)楣δ苄枨笠坏┏鰜恚枰僮鞯馁Y源、操作的方式立刻就能分析出來,因此資源URL和API的使用方式(GET, POST...)都很容易得到。

沒有了操作之間的依賴。資源之間雖然可能有關(guān)聯(lián),但是小得多。

對(duì)資源的操作也就那么幾種(獲取、新建、修改、刪除),API的一致性、自我描述性很強(qiáng),不需要過多解釋。

對(duì)于GET請(qǐng)求,我們都可以考慮使用緩存,因?yàn)樵赗ESTful的架構(gòu)中,GET請(qǐng)求代表獲取數(shù)據(jù),必須是安全、冪等的。

服務(wù)器無狀態(tài)

根據(jù)REST的架構(gòu)限制,RESTful的服務(wù)器必須是無狀態(tài)的,這意味著來自客戶的每一個(gè)請(qǐng)求必須包含服務(wù)器處理該請(qǐng)求所需的所有信息, 服務(wù)器不能利用任何已經(jīng)存儲(chǔ)的“上下文(context,在這里表示用戶的會(huì)話狀態(tài))”來處理新到來的請(qǐng)求,會(huì)話狀態(tài)只能由客戶端來保存,并且在請(qǐng)求時(shí)一并提供。

這里注意兩點(diǎn)。1. 服務(wù)器不能存儲(chǔ)“上下文”不代表連數(shù)據(jù)庫(kù)都不能有,“上下文”指那些在服務(wù)器內(nèi)存中的、非持久化的數(shù)據(jù)。2. 無狀態(tài)不代表不能有會(huì)話(sessions),無狀態(tài)僅僅指服務(wù)器無狀態(tài)。服務(wù)器不記錄、維護(hù)會(huì)話,但是會(huì)話狀態(tài)可以由客戶端在每次請(qǐng)求的時(shí)候提供。

我一開始以為無狀態(tài)與用戶登陸是沖突的,后來在Do sessions really violate RESTfulness? - StackOverflow上找到了一個(gè)令我滿意的解答。以下兩幅圖摘錄自這個(gè)答案。
無狀態(tài)的認(rèn)證機(jī)制:

What you need is storing username and password on the client and send it with every request. You don"t need more to do this than HTTP basic auth and an encrypted connection.
只需要將用戶名和密碼存儲(chǔ)在客戶端,然后客戶端每次發(fā)送請(qǐng)求都附帶上用戶名和密碼。要做到這點(diǎn)你只需要HTTP基本認(rèn)證(簡(jiǎn)單來說就是將用戶名和密碼放在HTTP頭部)和一個(gè)加密的連接(HTTPS)。
如果每次認(rèn)證,都要去數(shù)據(jù)庫(kù)查詢用戶的信息來核對(duì),那么響應(yīng)會(huì)非常慢,而且服務(wù)器也會(huì)有很大的性能損失。為了加快認(rèn)證的速度,最好在內(nèi)存中使用認(rèn)證緩存。這并不違背“無狀態(tài)”的限制,因?yàn)榫彺娴淖饔脙H僅起加速的作用,沒有緩存照樣能工作。

無狀態(tài)的第三方鑒權(quán)機(jī)制:

What about 3rd party clients? They cannot have the username and password and all the permissions of the users. So you have to store separately what permissions a 3rd party client can have by a specific user. So the client developers can register they 3rd party clients, and get an unique API key and the users can allow 3rd party clients to access some part of their permissions. Like reading the name and email address, or listing their friends, etc... After allowing a 3rd party client the server will generate an access token. These access token can be used by the 3rd party client to access the permissions granted by the user.
通過這個(gè)方式,用戶可以給第三方應(yīng)用授權(quán),讓第三方應(yīng)用拿著用戶的“令牌”訪問網(wǎng)站的一些服務(wù)。

以上兩幅圖講的是RESTful風(fēng)格的身份認(rèn)證機(jī)制。在實(shí)踐中最好使用OAuth 2.0框架。

無狀態(tài)增強(qiáng)了系統(tǒng)的故障恢復(fù)能力,因?yàn)樵诜?wù)器上沒有保存session的狀態(tài),所以恢復(fù)起來更容易。
更重要的是,無狀態(tài)意味著分布式系統(tǒng)能夠更好地工作,負(fù)載均衡器可以自由地將請(qǐng)求分發(fā)到任意的服務(wù)器。因?yàn)檎?qǐng)求中都已經(jīng)包含了服務(wù)器所需的所有信息,任何服務(wù)器都可以處理。
不僅僅是服務(wù)器,代理、網(wǎng)關(guān)、防火墻也可以理解消息,從而可以在不修改接口的情況下,增加更多強(qiáng)大的功能(比如代理緩存)。
并且,無狀態(tài)讓系統(tǒng)的橫向拓展能力強(qiáng)大。因?yàn)椴恍枰诓煌姆?wù)器之間同步session狀態(tài),所以服務(wù)器之間的溝通開銷很低。增加服務(wù)器的數(shù)量不會(huì)帶來明顯的性能損失(“1+1”更接近于“2”了)。

需要注意的是,REST不是一個(gè)“宗教”。在你自己的應(yīng)用中,遵循REST的同時(shí)應(yīng)該保持合適的尺度。通過權(quán)衡利弊,選擇總體效益最大的方案,即使這個(gè)方案有可能“稍微違反REST的原則”。詳見"REST is not a religion..." - stackoverflow
HATEOAS

圖片來自steps toward the glory of REST。

前面已經(jīng)討論了level 1和level 2,實(shí)際上REST還有一個(gè)更高的層次:HATEOAS(Hypermedia As The Engine Of Application State)。

對(duì)于客戶端的資源請(qǐng)求,服務(wù)器不僅要返回所請(qǐng)求的資源,而且要返回客戶端所處的狀態(tài)和可轉(zhuǎn)移的狀態(tài)。(客戶端有狀態(tài))

狀態(tài)可以簡(jiǎn)單地理解為客戶端展示的數(shù)據(jù)。可以把客戶端比喻成一個(gè)狀態(tài)機(jī),那么這個(gè)狀態(tài)機(jī)跳轉(zhuǎn)到一個(gè)新的狀態(tài),就會(huì)顯示新的內(nèi)容。“首頁(yè)”“文章列表”“某篇文章”就是三種客戶端狀態(tài)。

客戶端不需要提前知道應(yīng)用有哪些狀態(tài),而是根據(jù)服務(wù)端響應(yīng)的“可轉(zhuǎn)移的狀態(tài)”,提供給用戶選擇,從而發(fā)生狀態(tài)轉(zhuǎn)移。

用簡(jiǎn)單的話來說,在嚴(yán)格的RESTful架構(gòu)中,客戶端不需要提前知道服務(wù)端的API有哪些、怎么調(diào)用,在客戶端與服務(wù)器通信的過程中,服務(wù)端會(huì)告訴客戶端:在你當(dāng)前所處的狀態(tài)下,有哪些API可以使用、可以轉(zhuǎn)移到哪些狀態(tài)。

既然服務(wù)器是無狀態(tài)的,那么它要如何知道發(fā)起請(qǐng)求的用戶處于什么狀態(tài)呢?這就要求客戶端在發(fā)送請(qǐng)求的時(shí)候要攜帶上足夠的信息,讓服務(wù)器能夠判斷客戶端所處的狀態(tài)。

這就很像10086的“電話自動(dòng)語音應(yīng)答服務(wù)”:你想要查詢你的手機(jī)流量,只需要會(huì)撥打“10086”,對(duì)方會(huì)提示你按下哪些按鍵就能進(jìn)入哪些狀態(tài)。進(jìn)入下一個(gè)狀態(tài)以后,又會(huì)有語音提示你接下來能夠按哪些按鍵……最終,你能進(jìn)入到你想要的那個(gè)狀態(tài)(流量查詢服務(wù))。你需要記住的僅僅是“10086”這個(gè)號(hào)碼而已!

10086的語音提示相當(dāng)于Hypermedia,是驅(qū)動(dòng)應(yīng)用狀態(tài)轉(zhuǎn)換的“引擎”。

再進(jìn)一步想想,在RESTful架構(gòu)中,所有的狀態(tài)其實(shí)就組成了一顆樹(更準(zhǔn)確地說是網(wǎng)):根節(jié)點(diǎn)就是網(wǎng)站的基地址。在你獲取一個(gè)節(jié)點(diǎn)中的資源的同時(shí),服務(wù)器還會(huì)返回給你這個(gè)節(jié)點(diǎn)的邊:Hypermedia(超鏈接就是一種Hypermedia)。通過Hypermedia,你能夠知道相鄰節(jié)點(diǎn)的基本信息、地址。
結(jié)果就是:你能夠訪問到這顆樹的所有節(jié)點(diǎn),而你所需要提前知道的只是“如何到達(dá)根節(jié)點(diǎn)”而已!

每個(gè)節(jié)點(diǎn)就是一個(gè)狀態(tài)。用戶可以在這個(gè)狀態(tài)網(wǎng)中不斷跳轉(zhuǎn)。

這個(gè)例子(知乎)和這個(gè)例子(stackoverflow)也是不錯(cuò)的解釋。

wikipedia的解釋:a REST client should then be able to use server-provided links dynamically to discover all the available actions and resources it needs. As access proceeds, the server responds with text that includes hyperlinks to other actions that are currently available. There is no need for the client to be hard-coded with information regarding the structure or dynamics of the REST service.

這種架構(gòu)的優(yōu)勢(shì)非常明顯:前后端之間的耦合更加微弱。
隨著應(yīng)用功能的升級(jí)改變,“樹”的樣子會(huì)大大改變,但是只需要讓后端修改返回的資源內(nèi)容和Hypermedia,前端幾乎不用改動(dòng)。功能的演化更加靈活了。

“資源”和“狀態(tài)”的關(guān)系

現(xiàn)在你應(yīng)該明白R(shí)epresentational State Transfer中的State Transfer(狀態(tài)傳輸)是什么意思了:在HATEOAS中,服務(wù)端將客戶端所處的狀態(tài)和可以達(dá)到的狀態(tài)傳輸給客戶端。

等一下,在前面的資源小節(jié),我們不是說過傳輸?shù)氖琴Y源表示(representation)嗎?怎么這里又說傳輸?shù)氖菭顟B(tài)?

其實(shí)在REST架構(gòu)風(fēng)格中,“傳輸狀態(tài)”和“傳輸資源表示”是同一個(gè)意思。客戶端所處的狀態(tài),是由它接收到的資源表示來決定的。比如,客戶端接收到/user/csr/blogs資源,那么客戶端的狀態(tài)就變成/user/csr/blogs(顯示csr的文章列表)。
等一下,為什么客戶端會(huì)收到“/user/csr/blogs”資源?因?yàn)榭蛻舳苏?qǐng)求的就是“/user/csr/blogs”資源。
繼續(xù)追溯,為什么客戶端會(huì)請(qǐng)求這個(gè)資源?因?yàn)橛脩酎c(diǎn)擊了“查看文章列表”的鏈接(這個(gè)鏈接其實(shí)就是一個(gè)Hypermedia)。
繼續(xù)追溯,為什么有一個(gè)“查看文章列表”的鏈接顯示給用戶點(diǎn)擊?因?yàn)镠ATEOAS:服務(wù)端在返回上一個(gè)狀態(tài)(資源)的時(shí)候,會(huì)返回所有相鄰狀態(tài)的Hypermedia,其中就包括“查看文章列表”這個(gè)Hypermedia。客戶端會(huì)展示所有相鄰狀態(tài)的Hypermedia供用戶選擇。

按照從前往后的順序梳理一遍:

客戶端請(qǐng)求根資源
=> 服務(wù)器返回根資源的表示,以及相鄰資源的Hypermedia
=> 客戶端進(jìn)入“根資源”狀態(tài)(比如說,展示首頁(yè))
=> 客戶端顯示所有相鄰狀態(tài)的Hypermedia供用戶選擇(比如,在首頁(yè)有一個(gè)導(dǎo)航欄,里面有幾個(gè)鏈接)
=> 用戶選擇了某個(gè)Hypermedia(比如,點(diǎn)擊了“查看文章列表”的鏈接)
=> 客戶端請(qǐng)求“文章列表”資源
=> 服務(wù)器返回“文章列表”資源的表示,以及相鄰資源的Hypermedia
=> 客戶端進(jìn)入“文章列表”狀態(tài)
=> 客戶端顯示所有相鄰狀態(tài)的Hypermedia供用戶選擇(比如,在文章列表里,顯示所有文章的鏈接)
……

不難發(fā)現(xiàn),客戶端接收到一個(gè)新的資源表示,就會(huì)跳轉(zhuǎn)到新的狀態(tài),這個(gè)過程稱為狀態(tài)傳輸(服務(wù)器給客戶端傳輸新狀態(tài))。因此狀態(tài)傳輸是通過傳輸資源表示來完成的。

REST的字面意思

Representational State Transfer的語法結(jié)構(gòu)是(Representational (State Transfer)),在這里我們用的是representation的形容詞形式,意思是在表示層上的狀態(tài)傳輸。這個(gè)詞的字面意思是通過傳輸資源表示來傳輸客戶端狀態(tài)

REST的字面意思在網(wǎng)絡(luò)上有很多種理解,我參考了某位答主的兩個(gè)回答:https://stackoverflow.com/a/1... 和 https://stackoverflow.com/a/4... ,因?yàn)檫@位答主的回答最符合wikipedia的解釋:"The term is intended to evoke an image of how a well-designed Web application behaves: it is a network of Web resources (a virtual state-machine) where the user progresses through the application by selecting links, such as /user/tom, and operations such as GET or DELETE (state transitions), resulting in the next resource (representing the next state of the application) being transferred to the user for their use."

總結(jié)

至此,我們應(yīng)該能夠體會(huì)到REST已經(jīng)不僅僅是一種API風(fēng)格了,它是一種軟件架構(gòu)風(fēng)格(REST本身不是一種架構(gòu))。REST風(fēng)格的軟件架構(gòu)具有很強(qiáng)的演化、拓展能力:

一致的URL和HTTP動(dòng)詞使用:確保系統(tǒng)能夠接納多樣而又標(biāo)準(zhǔn)的客戶端,保證客戶端的演化能力。

無狀態(tài):保證了系統(tǒng)的橫向拓展能力、服務(wù)端的演化能力。

HATEOAS:保證了應(yīng)用本身的演化能力(功能增加、改變)。

這3點(diǎn)是單單對(duì)演化拓展優(yōu)勢(shì)的說明,這個(gè)回答總結(jié)了REST的6個(gè)約束分別對(duì)應(yīng)的優(yōu)點(diǎn)。


參考資料

Roy Fielding 提出REST的論文
Representational state transfer - wikipedia
What exactly is RESTful programming? - stackoverflow
Do sessions really violate RESTfulness? - stackoverflow
steps toward the glory of REST - Martin Fowler(軟件開發(fā)“教父”)

怎樣用通俗的語言解釋REST,以及RESTful? - 知乎
REST風(fēng)格的優(yōu)勢(shì)是什么? - 知乎
RESTful API 設(shè)計(jì)指南
What does Representational State mean in REST? - stackoverflow
Clarifying REST
REST APIs must be hypertext-driven - Roy Fielding

REST tutorial 1
REST tutorial 2

用戶注冊(cè)、登陸、登出的RESTful API設(shè)計(jì)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/11856.html

相關(guān)文章

  • 那些年,我們一起誤解過的REST

    摘要:通過增刪查改,引起資源狀態(tài)的改變,稱為狀態(tài)轉(zhuǎn)移。用于獲取資源的元信息。方法與方法類似,都可以查詢資源的元信息放在的,但不會(huì)返回資源的表述。表示請(qǐng)求有問題,如參數(shù)錯(cuò)誤等。表示當(dāng)前請(qǐng)求的某前置條件不符合。網(wǎng)關(guān)錯(cuò)誤,從上游服務(wù)器收到無效響應(yīng)。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由sammyshen 發(fā)表于云+社區(qū)專欄 最近幾年REST API越來越流行,特別是...

    DesGemini 評(píng)論0 收藏0
  • PHP / Laravel API 開發(fā)推薦閱讀清單

    showImg(https://segmentfault.com/img/bV6aHV?w=1280&h=800); 社區(qū)優(yōu)秀文章 Laravel 5.5+passport 放棄 dingo 開發(fā) API 實(shí)戰(zhàn),讓 API 開發(fā)更省心 - 自造車輪。 API 文檔神器 Swagger 介紹及在 PHP 項(xiàng)目中使用 - API 文檔撰寫方案 推薦 Laravel API 項(xiàng)目必須使用的 8 個(gè)...

    shmily 評(píng)論0 收藏0
  • 理解RESTful架構(gòu)與json-server模擬REST api的使用

    摘要:一什么是架構(gòu)即的縮寫,我們把他翻譯為表述性狀態(tài)傳遞,是博士在年他的博士論文中提出來的一種軟件架構(gòu)風(fēng)格。是個(gè)無狀態(tài)的協(xié)議,所以狀態(tài)就保存在服務(wù)器端。只要少量的數(shù)據(jù)就可使用,支持和。同時(shí)支持,同時(shí)提供一系列的查詢方法如。 一、什么是RESTful架構(gòu)? REST即Representational State Transfer的縮寫,我們把他翻譯為表述性狀態(tài)傳遞,是Roy Fielding博...

    Atom 評(píng)論0 收藏0
  • 后端技術(shù)精選

    摘要:服務(wù)教程在它提出十多年后的今天,已經(jīng)成為最重要的應(yīng)用技術(shù)之一。全方位提升網(wǎng)站打開速度前端后端新的技術(shù)如何在內(nèi)完整打開網(wǎng)站會(huì)直接影響用戶的滿意度及留存率,在前端后端數(shù)據(jù)緩存加速等等方面都有諸多可以提升。 HTTPS 原理剖析與項(xiàng)目場(chǎng)景 最近手頭有兩個(gè)項(xiàng)目,XX 導(dǎo)航和 XX 產(chǎn)業(yè)平臺(tái),都需要使用 HTTPS 協(xié)議,因此,這次對(duì) HTTPS 協(xié)議做一次整理與分享。 使用緩存應(yīng)該注意哪些問題...

    GitCafe 評(píng)論0 收藏0
  • 后端技術(shù)精選

    摘要:服務(wù)教程在它提出十多年后的今天,已經(jīng)成為最重要的應(yīng)用技術(shù)之一。全方位提升網(wǎng)站打開速度前端后端新的技術(shù)如何在內(nèi)完整打開網(wǎng)站會(huì)直接影響用戶的滿意度及留存率,在前端后端數(shù)據(jù)緩存加速等等方面都有諸多可以提升。 HTTPS 原理剖析與項(xiàng)目場(chǎng)景 最近手頭有兩個(gè)項(xiàng)目,XX 導(dǎo)航和 XX 產(chǎn)業(yè)平臺(tái),都需要使用 HTTPS 協(xié)議,因此,這次對(duì) HTTPS 協(xié)議做一次整理與分享。 使用緩存應(yīng)該注意哪些問題...

    explorer_ddf 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<