1. 程式人生 > >【轉】Restful是什麼

【轉】Restful是什麼

REST的概念是什麼

維基百科  表現層狀態轉換(REST,英文:Representational State Transfer)是Roy Thomas Fielding博士於2000年在他的博士論文中提出來的一種全球資訊網軟體架構風格,目的是便於不同軟體/程式在網路(例如網際網路)中互相傳遞資訊。 知乎  [資源]表現層狀態轉換(REST,英文:[Resource] Representational State Transfer),通俗翻譯為:資源在網路中以某種表現形式進行狀態轉移。

 Resource:資源,即資料(網路的核心),比如 goods,fruits等;

Representational:某種表現形式,比如用JSON,XML,JPEG等;

State Transfer:狀態變化,通過HTTP動詞實現。

我們為什麼需要REST

我們先了解一下在REST沒有出現之前的Web開發是什麼樣的?

早期的Web 專案一般是在伺服器端進行渲染,伺服器程序從資料庫獲取資料後,然後利用後端模板引擎(比如Velocity、Freemaker 等)或者直接在HTML 模板中嵌入後端語言(比如JSP、PHP),將資料載入進來生成HTML,然後通過網路傳輸到使用者的瀏覽器中,最後被瀏覽器解析成可見的頁面。具體的過程如下圖所示:

 

此時大多數伺服器架構都是這種 MVC 模式,前端只需要一次HTTP請求就可以返回整個頁面內容,載入速度可能會稍微快些。但是它的缺點也非常明顯,前端寫完靜態頁面,要讓後臺去套模板,每次前端稍有改動,後臺對應的模板頁面同時也需要改動,而且頁面中可能會包含大量複雜的 JS程式碼,比如美工同學(當時的前端)需要通過JS寫介面的互動,而後端同學又需要通過JS實現資料的渲染,非常地麻煩。

當然事情麻煩歸麻煩,但還不至於引發新的技術革命,而真正推動REST發展的是移動網際網路的出現。由於多終端裝置的相容性需求,從前的服務端渲染已經很難滿足要求了。服務端不可能針對每一個Client渲染一套介面,如果服務端只提供需要的資料,而具體介面的渲染完全交給具體的Client來完成,因此催生了REST的發展和普及。

RESTful可以通過一套統一的介面為 Web、iOS和Android提供服務,另外對於很多平臺來說(比如像Facebook,Twiter、微博、微信等開放平臺),它們不需要有顯式的前端,只需要一套提供服務的介面,於是RESTful便是它們最好的選擇。

前端渲染和後端渲染的優勢是什麼

隨著前端渲染引擎的發展,新興的Angular,React,Vue等的出現,真正地實現了前後端分離解耦:前端專注於UI,負責View和Controller層,後端專注於業務/資料處理,負責Model層,兩端通過設計好的REST API進行互動

後端渲染的優點:

 ●  1、對搜尋引擎友好,這樣做有利於 SEO。
 ●  2、載入時間短,後端渲染載入完成後就直接顯示HTML,但前端渲染在載入完成後還需要有段js 渲染的時間。

前端渲染的優點

 ●  1、讓前後端的職責更清晰,分工更合理高效。前後端業務分離,後端只需要提供資料介面,前端在開發時也不需要部署對應的後端環境,可以通過Mock資料進行併發開發
 ●  2、計算量轉移,原本由伺服器執行的渲染任務轉移給了客戶端,這在大量使用者訪問的時候大大減輕後端的壓力。讓後端專注做後端應該做的事情,效能將大大提高,因為伺服器做的事情確實減小了。

前後端分離+Node層優點:

 ●  通過 Node,Web Server 層也是 JavaScript 程式碼,這意味著部分程式碼可前後複用,需要 SEO 的場景可以在服務端同步渲染,由於非同步請求太多導致的效能問題也可以通過服務端來緩解,結合了前兩種模式的優點。

 什麼樣的REST才是『正宗』的

無狀態原則

遵循REST正規化的系統是無狀態的,這意味著伺服器不需要知道客戶端處於什麼狀態,反之亦然。這樣,即使沒有看到以前的訊息,伺服器和客戶端都可以理解收到的任何訊息。這種的無狀態約束是通過使用資源來實現的。資源是Web中的特定名詞——它描述了任何你可能需要儲存或傳送到其他服務的物件或文件。

無狀態原則是RESTful架構設計中一個非常重要的原則,無狀態是相對於有狀態而言的,我們首先看一下什麼是有狀態的。

Web服務的狀態一般指的是請求的狀態,是客戶端和服務端進行互動操作時所留下來的公共資訊(比如,使用者的資訊等)。這些資訊可以被指定在不同的作用域中(如request、session、application等),通常由服務端來儲存這些資訊。

而無狀態的Web服務是指每一個Web請求都是獨立的,服務端沒有儲存任何客戶端的狀態資訊,所以客戶端傳送的請求必須包含有能夠讓服務端理解請求的全部資訊。

另外由於REST系統通過資源上的標準操作進行互動,因此它們不依賴於介面的實現,使得RESTful應用程式具有可靠性、快速性和可擴充套件性。

 

前後端通訊機制

1、請求方式
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

2、接收內容
在伺服器向客戶端傳送資料有效載荷的情況下,伺服器必須content-type在響應的頭部包含一個。這個content-type頭域告訴客戶端它在響應主體中傳送的資料的型別。這些內容型別是MIME型別,就像它們在accept請求頭的欄位中一樣。該content-type伺服器在響應傳送迴應的客戶機中指定的選項之一accept的請求的欄位。

例如,當客戶端使用此GET請求訪問具有資源id23的articles資源時:


GET /articles/23 HTTP/1.1 Accept: text/html, application/xhtml

伺服器可能會使用響應頭髮回內容:

 
 
  
HTTP/1.1 200 (OK) Content-Type: text/html

這將意味著所請求的內容被返回的響應體用content-type的text/html,該客戶表示,將能夠接受。

3、返回狀態
在伺服器向客戶端傳送資料有效載荷的情況下,伺服器必須content-type在響應的頭部包含一個。這個content-type頭域告訴客戶端它在響應主體中傳送的資料的型別。這些內容型別是MIME型別,就像它們在accept請求頭的欄位中一樣。該content-type伺服器在響應傳送迴應的客戶機中指定的選項之一accept的請求的欄位。

例如,當客戶端使用此GET請求訪問具有資源id23的articles資源時:

 
 
  
GET /articles/23 HTTP/1.1 Accept: text/html, application/xhtml

伺服器可能會使用響應頭髮回內容:

 
 
  
HTTP/1.1 200 (OK) 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(無內容)。如果操作失敗,則返回可能對應於遇到的問題的最具體的狀態碼。

4、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#