Resource:資源,即數據(網絡的核心),好比 goods,fruits等;css
Representational:某種表現形式,好比用JSON,XML,JPEG等;html
State Transfer:狀態變化,經過HTTP動詞實現。
咱們先了解一下在REST沒有出現以前的Web開發是什麼樣的?前端
早期的Web 項目通常是在服務器端進行渲染,服務器進程從數據庫獲取數據後,而後利用後端模板引擎(好比Velocity、Freemaker 等)或者直接在HTML 模板中嵌入後端語言(好比JSP、PHP),將數據加載進來生成HTML,而後經過網絡傳輸到用戶的瀏覽器中,最後被瀏覽器解析成可見的頁面。具體的過程以下圖所示:數據庫
此時大多數服務器架構都是這種 MVC 模式,前端只須要一次HTTP請求就能夠返回整個頁面內容,加載速度可能會稍微快些。可是它的缺點也很是明顯,前端寫完靜態頁面,要讓後臺去套模板,每次前端稍有改動,後臺對應的模板頁面同時也須要改動,並且頁面中可能會包含大量複雜的 JS代碼,好比美工同窗(當時的前端)須要經過JS寫界面的交互,然後端同窗又須要經過JS實現數據的渲染,很是地麻煩。json
固然事情麻煩歸麻煩,但還不至於引起新的技術革命,而真正推進REST發展的是移動互聯網的出現。因爲多終端設備的兼容性需求,從前的服務端渲染已經很難知足要求了。服務端不可能針對每個Client渲染一套界面,若是服務端只提供須要的數據,而具體界面的渲染徹底交給具體的Client來完成,所以催生了REST的發展和普及。後端
RESTful能夠經過一套統一的接口爲 Web、iOS和Android提供服務,另外對於不少平臺來講(好比像Facebook,Twiter、微博、微信等開放平臺),它們不須要有顯式的前端,只須要一套提供服務的接口,因而RESTful即是它們最好的選擇。瀏覽器
隨着前端渲染引擎的發展,新興的Angular,React,Vue等的出現,真正地實現了先後端分離解耦:前端專一於UI,負責View和Controller層,後端專一於業務/數據處理,負責Model層,兩端經過設計好的REST API進行交互。服務器
後端渲染的優勢:微信
● 一、對搜索引擎友好,這樣作有利於 SEO。
● 二、加載時間短,後端渲染加載完成後就直接顯示HTML,但前端渲染在加載完成後還須要有段js 渲染的時間。網絡
前端渲染的優勢:
● 一、讓先後端的職責更清晰,分工更合理高效。先後端業務分離,後端只須要提供數據接口,前端在開發時也不須要部署對應的後端環境,能夠經過Mock數據進行併發開發。
● 二、計算量轉移,本來由服務器執行的渲染任務轉移給了客戶端,這在大量用戶訪問的時候大大減輕後端的壓力。讓後端專一作後端應該作的事情,性能將大大提升,由於服務器作的事情確實減少了。
先後端分離+Node層優勢:
● 經過 Node,Web Server 層也是 JavaScript 代碼,這意味着部分代碼可先後複用,須要 SEO 的場景能夠在服務端同步渲染,因爲異步請求太多致使的性能問題也能夠經過服務端來緩解,結合了前兩種模式的優勢。
遵循REST範式的系統是無狀態的,這意味着服務器不須要知道客戶端處於什麼狀態,反之亦然。這樣,即便沒有看到之前的消息,服務器和客戶端均可以理解收到的任何消息。這種的無狀態約束是經過使用資源來實現的。資源是Web中的特定名詞——它描述了任何你可能須要存儲或發送到其餘服務的對象或文檔。
無狀態原則是RESTful架構設計中一個很是重要的原則,無狀態是相對於有狀態而言的,咱們首先看一下什麼是有狀態的。
Web服務的狀態通常指的是請求的狀態,是客戶端和服務端進行交互操做時所留下來的公共信息(好比,用戶的信息等)。這些信息能夠被指定在不一樣的做用域中(如request、session、application等),一般由服務端來保存這些信息。
而無狀態的Web服務是指每個Web請求都是獨立的,服務端沒有保存任何客戶端的狀態信息,因此客戶端發送的請求必須包含有可以讓服務端理解請求的所有信息。
另外因爲REST系統經過資源上的標準操做進行交互,所以它們不依賴於接口的實現,使得RESTful應用程序具備可靠性、快速性和可擴展性。
一、請求方式
REST要求客戶端向服務端發出請求以得到或修改服務器上的數據。請求一般由如下部分組成:
● 一個HTTP動詞,它定義了要執行的操做類型
● 一個頭部,它容許客戶端傳遞關於請求的信息
● 一條資源的路徑
● 一個包含數據的可選消息主體
(1)對於HTTP動詞
在REST系統中咱們使用4個基本HTTP動詞來與資源進行交互:
● GET - 檢索特定資源(經過id)或資源集合
● POST - 建立一個新資源
● PUT - 更新特定資源(經過ID)
● DELETE - 按ID刪除特定資源
(2)對於請求頭部
客戶端向服務端發送它可以接收的內容的類型,而該類型是經過一個叫Accept的字段發送的。經過這種方式能夠確保服務端不會發送客戶端沒法理解或者沒法處理的數據。
用於指定Accept字段的類型爲MIME類型,它是由一個type和一個subtype經過斜線(/)分隔組成的。你能夠在MDN Web文檔中查看更多關於MIME類型的介紹。
例如,包含HTML的文本文件類型指定爲text/html,而包含CSS的文本文件須要指定爲text/css,通常的文本文件將被指定爲text/plain(若是不指定,則默認值爲text/plain)。假如客戶期待的類型爲text/css,而接收到的類型text/plain,那麼客戶端將沒法識別它。如下列舉了其餘的type和subtype:
● image — image/png, image/jpeg, image/gif
● audio — audio/wav, image/mpeg
● video — video/mp4, video/ogg
● application — application/json, application/pdf, application/xml, application/octet-stream
(3)對於資源路徑
在RESTful API中,每個請求的動做都必須做用於一個資源路徑上,因此資源路徑的設計就是爲了讓客戶端可以理解它所進行的操做是什麼。
一般狀況下,路徑的第一部分應該是資源的複數形式。RESTful中這種路徑嵌套方式簡單易讀,也更容易理解。示例以下:
https://www.alipay.com/customers/22/orders/11
該RESTful API指向的路徑很是清晰,由於它具備層次性和自描述性。該示例中,咱們查詢了id號爲22這位顧客的一筆訂單,而且該訂單的id號爲11。
路徑必須包含它所須要的可以準肯定位它所表明的資源位置的信息。可是,若是引用的資源爲列表或集合時,就不須要再向POST請求添加id這樣的惟一標識了,由於在服務端將爲該新對象生成一個惟一標識id的。例如向顧客集合中新增一位顧客:
POST https://www.alipay.com/customers
若是咱們試圖訪問單個資源,則須要在路徑後面添加一個id,例如經過指定的id來查詢一位顧客:
GET https://www.alipay.com/customers/:id
或者,經過指定的id來刪除一位顧客:
DELETE https://www.alipay.com/customers/:id
二、接收內容
在服務器向客戶端發送數據有效載荷的狀況下,服務器必須content-type在響應的頭部包含一個。這個content-type頭域告訴客戶端它在響應主體中發送的數據的類型。這些內容類型是MIME類型,就像它們在accept請求頭的字段中同樣。該content-type服務器在響應發送迴應的客戶機中指定的選項之一accept的請求的字段。
例如,當客戶端使用此GET請求訪問具備資源id23的articles資源時:
Accept: text/html, application/xhtml
服務器可能會使用響應頭髮回內容:
Content-Type: text/html
這將意味着所請求的內容被返回的響應體用content-type的text/html,該客戶表示,將可以接受。
三、返回狀態
在服務器向客戶端發送數據有效載荷的狀況下,服務器必須content-type在響應的頭部包含一個。這個content-type頭域告訴客戶端它在響應主體中發送的數據的類型。這些內容類型是MIME類型,就像它們在accept請求頭的字段中同樣。該content-type服務器在響應發送迴應的客戶機中指定的選項之一accept的請求的字段。
例如,當客戶端使用此GET請求訪問具備資源id23的articles資源時:
Accept: text/html, application/xhtml
服務器可能會使用響應頭髮回內容:
Content-Type: text/html
來自服務器的響應包含狀態代碼,以提醒客戶有關操做成功的信息。做爲開發人員,您不須要知道每一個狀態代碼(其中有不少),但您應該知道最多見的狀態代碼以及它們的使用方式:
狀態碼 | 含義 |
---|---|
200 (OK) | 這是成功HTTP請求的標準響應。 |
201 (CREATED) | 這是致使成功建立項目的HTTP請求的標準響應。 |
204 (NO CONTENT) | 這是成功HTTP請求的標準響應,響應正文中沒有任何內容被返回。 |
400 (BAD REQUEST) | 因爲請求語法錯誤,大小過大或其餘客戶端錯誤,沒法處理該請求。 |
403 (FORBIDDEN) | 客戶端沒有權限訪問此資源。 |
404 (NOT FOUND) | 此時沒法找到該資源。它可能已被刪除,或尚不存在。 |
500 (INTERNAL SERVER ERROR) | 若是沒有更多可用的特定信息,則通用答案意外失敗。 |
對於每一個HTTP動詞,服務器在成功時應返回預期的狀態代碼:
● GET - 返回200(OK)。
● POST - 返回201(建立)。
● PUT - 返回200(OK)。
● DELETE - 返回204(無內容)。若是操做失敗,則返回可能對應於遇到的問題的最具體的狀態碼。
四、CRUD示例說明
如今咱們須要設計一個班級管理的系統,其中須要有班級信息和班級的學生信息。那咱們該怎麼爲它設計REST接口呢?能夠按照如下幾點思考:
● 使用什麼樣的請求方式?
● 服務端返回是什麼樣的?
● 經過什麼樣的content-type
傳輸內容?
● 首先定義班級和學生的數據模型以下。
「class」: { "id": <Integer>,
「name」: <String>,
}
「num」: <Integer>
}
「 student」: {
"id": <Integer>,
「name」: <String>,
「age」: <Integer>
}
}
GET請求:
接口 | 請求方式 | 傳輸格式(Content-type) | 返回狀態 |
---|---|---|---|
/classes | GET | application/json | 200 (OK) |
/classes/:id | GET | application/json | 200 (OK) |
/classes/:id/students | GET | application/json | 200 (OK) |
/classes/:id/students/:id | GET | application/json | 200 (OK) |
POST請求:
接口 | 請求方式 | 傳輸格式(Content-type) | 返回狀態 |
---|---|---|---|
/classes | POST | application/json | 201 (CREATED) |
/classes/:id/students | POST | application/json | 201 (CREATED) |
PUT請求:
接口 | 請求方式 | 傳輸格式(Content-type) | 返回狀態 |
---|---|---|---|
/classes/:id | PUT | application/json | 200 (OK) |
/classes/:id/students/:id | PUT | application/json | 200 (OK) |
DELETE請求:
接口 | 請求方式 | 傳輸格式(Content-type) | 返回狀態 |
---|---|---|---|
/classes/:id | DELETE | application/json | 204 (NO CONTENT) |
/classes/:id/students/:id | DELETE | application/json | 204 (NO CONTENT) |
本文介紹了REST的相關概念,同時介紹了咱們爲何須要REST,分析了前端渲染和後端渲染的優點是什麼,而後再介紹了什麼樣的REST纔是"正宗"的,最後經過一個示例完整的演示了CRUD的操做。
轉自:https://yq.aliyun.com/articles/663741?spm=a2c4e.11155472.0.0.42411dfdth2qeD#