1. 程式人生 > >REST架構風格簡介

REST架構風格簡介

http://www.cnblogs.com/loveis715/p/4669091.html

  一說到REST,我想大家的第一反應就是“啊,就是那種前後臺通訊方式。”但是在要求詳細講述它所提出的各個約束,以及如何開始搭建REST服務時,卻很少有人能夠清晰地說出它到底是什麼,需要遵守什麼樣的準則。

  在您將看到的這一篇文章中,我們將對REST,尤其是基於HTTP的REST服務進行詳細地介紹。通過這些文章,您不僅可以瞭解到什麼是REST,更能清晰地瞭解到您在編寫REST服務時所需要遵守的各個守則,設計RESTful API時需要考慮的各種因素以及實現過程中可能遇到的問題等內容。

REST示例

  我想,很多讀者可能並不太清楚REST到底是一個什麼概念。那麼,首先讓我們來看一個簡單的基於HTTP的REST服務示例。

  假設使用者正在訪問一個電子商務網站www.egoods.com。該網站對其所銷售的各個物品進行了詳細分類。當用戶登入該網站進行購物時,他首先需要在該網站上選擇其所需要尋找物品的分類,進而列出屬於該分類的各個物品。

  當然,雖然從業務邏輯的角度來說這個流程非常簡單,但實際上瀏覽器向後臺傳送了多個請求:頁面邏輯在頁面載入時將首先得到所有的商品分類,並將這些分類顯示在了頁面中。在使用者選擇了一個分類的時候,頁面邏輯將傳送一個請求得到該分類的詳細資訊,併發送另外一個請求來得到該分類的商品列表:

  在通過瀏覽器的除錯功能檢視這些請求的時候,我們可以看到其首先向www.egoods.com/api/categories傳送一個GET請求,以取得所有的商品分類:

1 GET /api/categories
2 Host: www.egoods.com
3 Authorization: Basic xxxxxxxxxxxxxxxxxxx
4 Accept: application/json

  而服務端將返回所有的類別:

複製程式碼
 1 HTTP/1.1 200 OK
 2 Content-Type: application/json
 3 Content-Length: xxx
4 5 [ 6 { 7 "label" : "食品", 8 "url" : "/api/categories/1" 9 }, { 10 "label" : "服裝", 11 "url" : "/api/categories/2" 12 } 13 ... 14 { 15 "label" : "電子裝置", 16 "url" : "/api/categories/25" 17 } 18 ]
複製程式碼

  該響應返回了一個用JSON表示的陣列。該陣列中的每個元素包含了兩部分資訊:使用者能夠讀懂的表示分類名稱的label以及相應分類所對應的URL。其中Label所記錄的分類名稱將在頁面中顯示給使用者。而在使用者根據label所標示的分類名選擇了一個分類的時候,頁面邏輯會取得該分類所對應的URL並向該URL 傳送請求,以得到該分類的詳細資訊。例如在使用者點選了“食品”這個分類的時候,瀏覽器將會向伺服器傳送如下的請求:

1 GET /api/categories/1
2 Host: www.egoods.com
3 Authorization: Basic xxxxxxxxxxxxxxxxxxx
4 Accept: application/json

  這一次,頁面邏輯根據使用者對分類的選擇“食品”來得到了其所對應的URL,並向該URL傳送了一個GET請求。而該請求所得到的響應則為:

複製程式碼
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx
 
{
   "url" : "/api/categories/1",
   "label" : "Food",
   "items_url" : "/api/items?category=1",
   "brands" : [
         {
            "label" : "友臣",
            "brand_key" : "32073",
            "url" : "/api/brands/32073"
         }, {
            "label" : "樂事",
            "brand_key" : "56632",
            "url" : "/api/brands/56632"
         }
         ...
   ],
   "hot_searches" : …
}
複製程式碼

  該響應略為複雜。首先,響應中的URL標示了“食品”分類所對應的URL。而label屬性則和前面一樣,用來在頁面上顯示分類的名稱。一個較為特殊的屬性則是items_url。其用來標示獲取屬於食品分類的各個產品的URL。而屬性brands則用來列出在“食品”分類中的著名品牌,例如友臣,樂事等。這些品牌被組織為一個物件陣列,而陣列中的每個物件都擁有label,url等屬性。在這些屬性的幫助下,頁面可以列出這些著名品牌的名稱,並允許使用者通過點選跳轉到這些品牌所對應的頁面上。除了這些屬性之外,Food分類還包含了其它一系列屬性,如表示當前其它使用者正在搜尋的hot_searches屬性等,這裡就不再贅述。

  該響應有一個問題,那就是符合使用者篩選條件的各個產品並沒有包含在該響應中。這是因為頁面所列出的各個產品是根據使用者所設定的篩選條件,即其選擇的品牌以及搜尋關鍵字而變化的。因此,頁面邏輯會根據屬性items_url以及使用者所設定的搜尋條件組合成為目標URL,再次傳送請求到後臺,以請求需要在頁面中展現的各個物品。

  例如使用者在只想瀏覽屬於樂事品牌的食品時,其可以鉤選樂事這個品牌,那麼此時的URL將由食物分類的items_url以及表示按照品牌進行篩選的URL引數共同組成:

1 GET /api/items?category=1&brand_key=56632
2 Host: www.egoods.com
3 Authorization: Basic xxxxxxxxxxxxxxxxxxx
4 Accept: application/json

  現在讓我們來總結一下上面所展示的基於HTTP的REST系統的整個執行流程。在開始的時候,我們拿到了所有分類的列表。列表中的各個條目不僅僅包含了使用者可以看到的分類名稱等資訊,更擁有一個額外的URL屬性。在使用者選擇該列表中的一項時,頁面邏輯將會向對應的URL傳送一個請求,以獲得該專案的詳細資訊。在這個詳細資訊中,一些內容又包含了一些其它的URL,從而使得頁面邏輯又能通過該URL屬性發送請求。

  您也許會說,哎,這不和我們現有系統的執行流程一樣的嘛。是的。在上面所舉出的例子中,我們也更偏重地描述了REST系統所需要具有的HATEOAS(Hypermedia As The Engine Of Application State)特性。正是由於這個特性已經在大家所建立的系統裡面廣泛地使用了,因此我更希望從熟悉的地方入手,而不是開始就非常教條地說REST一定要這樣,一定要那樣,徒增了學習的難度。

  反過來說,上面所展示的REST服務並不具有典型性。在充分了解了REST後,您會發現,REST在系統設計上的視角將不再把流程放在了最優先的位置。

  而在後面的章節中,我們則會逐漸展開,詳細地介紹如何建立一個純正的基於HTTP的REST服務。

REST的定義

  OK,現在讓我們來看看REST的定義。Wikipedia是這樣描述它的:

Representational State Transfer (REST) is a software architecture style consisting of guidelines and best practices for creating scalable web services. REST is a coordinated set of constraints applied to the design of components in a distributed hypermedia system that can lead to a more performant and maintainable architecture.

  從上面的定義中,我們可以發現REST其實是一種組織Web服務的架構,而並不是我們想象的那樣是實現Web服務的一種新的技術,更沒有要求一定要使用HTTP。其目標是為了建立具有良好擴充套件性的分散式系統。

  反過來,作為一種架構,其提出了一系列架構級約束。這些約束有:

  1. 使用客戶/伺服器模型。客戶和伺服器之間通過一個統一的介面來互相通訊。
  2. 層次化的系統。在一個REST系統中,客戶端並不會固定地與一個伺服器打交道。
  3. 無狀態。在一個REST系統中,服務端並不會儲存有關客戶的任何狀態。也就是說,客戶端自身負責使用者狀態的維持,並在每次傳送請求時都需要提供足夠的資訊。
  4. 可快取。REST系統需要能夠恰當地快取請求,以儘量減少服務端和客戶端之間的資訊傳輸,以提高效能。
  5. 統一的介面。一個REST系統需要使用一個統一的介面來完成子系統之間以及服務與使用者之間的互動。這使得REST系統中的各個子系統可以獨自完成演化。

  如果一個系統滿足了上面所列出的五條約束,那麼該系統就被稱為是RESTful的。

  下面我們再次通過電子商務網站egoods這個示例來幫助我們理解這些約束。首先,egoods是一個電子商務網站。使用者需要通過瀏覽器,手機或者網站所釋出的瀏覽應用來訪問該網站的內容。因此其使用的自然是客戶/伺服器模型。而在瀏覽過程中,使用者需要訪問不同型別的資料,如商品描述、購物車等資訊。這些資訊可能由egoods網站服務中不同的伺服器來提供的,因此在使用者瀏覽過程中可能需要與不止一個伺服器進行互動。如果在服務端儲存了有關客戶的任何狀態,那麼在使用者與不同伺服器進行互動的時候,客戶的狀態就需要在這些服務之間進行同步,大大地增加了系統的複雜度。因此,REST要求客戶端自行維護狀態,並在每次傳送請求的時候提供自身所儲存的處理該請求所必需的資訊。而恰當地使用快取這一條也非常容易理解。在客戶端請求一個自上次請求後沒有發生過變化的資訊時,如產品分類列表,服務端僅僅需要返回一個304響應即可。

  這裡您可以看到,前四條約束中除了無狀態這條約束較為特別之外,其它三條約束在基於HTTP的Web服務中都很常見,也較容易達成。而無狀態約束在其它型別的Web服務中並不十分常見,因此如何避免違反該約束是在實現REST服務時最常討論的話題。其不僅僅會影響到很多功能的設計,更是REST系統擴充套件性的關鍵。因此在後面的章節中,我們會對無狀態約束單獨進行講解。

  在簡單地介紹了前四個約束之後,我們就需要著重講解統一介面這個約束了。可以說,前面的四個約束實際上都較為容易達成。唯一需要注意的無非是是否某些技術實現違反了這些約束。而第五條約束,統一介面,可以說是REST服務設計的核心所在,也是決定REST服務設計的成敗之處。在實現一個基於HTTP的REST服務時,軟體開發人員不僅僅需要考慮REST所設定的一系列約束,更需要考慮HTTP各組成的語意,HTTP相關技術如何與REST服務約束結合,如何保持前後向相容性以及如何進行版本管理等問題,才能給出一個自然的,具有較高易用性和較強生命力的REST系統。

  而在介紹統一介面約束之前,我們則需要了解一下和REST密切相關的兩個名詞:資源和狀態。可以說,資源是REST系統的核心概念。所有的設計都會以資源為中心,包括如何對資源進行新增,更新,查詢以及修改等。而資源本身則擁有一系列狀態。在每次對資源進行新增 ,刪除或修改的時候,資源就將從一個狀態轉移到另外一個狀態。

  比如說,在egoods中,商品的分類就是一種資源。該資源有很多例項,包括表示食品的分類,其所對應的URL是“/api/categories/1”。同樣地,食品的品牌也是一種資源。這些資源的例項都對應著一個當前的狀態。在修改了一個資源例項之後,比如修改了食品分類中的熱搜關鍵字,那麼其將對應著一個新的狀態。這種狀態之間的變化被稱為是狀態的轉移。

  在大概瞭解了REST系統中的資源和狀態的定義後,我們來看看統一介面這個約束。該約束又包含了四個子約束:

  1. 每個資源都擁有一個資源標識。每個資源的資源標識可以用來唯一地標明該資源。
  2. 訊息的自描述性。在REST系統中所傳遞的訊息需要能夠提供自身如何被處理的足夠資訊。例如該訊息所使用的MIME型別,是否可以被快取等。
  3. 資源的自描述性。一個REST系統所返回的資源需要能夠描述自身,並提供足夠的用於操作該資源的資訊,如如何對資源進行新增,刪除以及修改等操作。也就是說,一個典型的REST服務不需要額外的文件對如何操作資源進行說明。
  4. HATEOAS。即客戶只可以通過服務端所返回各結果中所包含的資訊來得到下一步操作所需要的資訊,如到底是向哪個URL傳送請求等。也就是說,一個典型的REST服務不需要額外的文件標示通過哪些URL訪問特定型別的資源,而是通過服務端返回的響應來標示到底能在該資源上執行什麼樣的操作。一個REST服務的客戶端也不需要知道任何有關哪裡有什麼樣的資源這種資訊。

  現在,讓我們仍然以egoods作為示例來解釋一下上面四個子約束。

  在前面的章節中,我們已經看到了從egoods所返回的表示食品這個分類的響應:

複製程式碼
 1 HTTP/1.1 200 OK
 2 Content-Type: application/json
 3 Content-Length: xxx
 4 
 5 {
 6    "url" : "/api/categories/1",
 7    "label" : "Food",
 8    "items_url" : "/api/items?category=1",
 9    "brands" : [
10          {
11             "label" : "友臣",
12             "brand_key" : "32073",
13             "url" : "/api/brands/32073"
14          }, {
15             "label" : "樂事",
16             "brand_key" : "56632",
17             "url" : "/api/brands/56632"
18          }
19          ...
20    ],
21    "hot_searches" : …
22 }
複製程式碼

  首先我們看到的是,該響應通過Content-Type響應頭來標示響應中所包含的資訊是按照JSON格式來組織的。在看到了該響應頭中所標示的格式之後,訊息的接收方就可以按照JSON的格式理解或分析該響應中的負載。這也便是訊息的自描述性。

  當然,訊息的自描述性不僅僅包含如何解析其所攜帶的負載。在一個基於HTTP的REST系統中,我們可以通過使用大部分HTTP標準所提供的功能來提高訊息的自描述性。由於這些功能已經擁有了完備的文件,被廣大的軟體開發人員所熟知,並得到了眾多瀏覽器廠商以及Web類庫的支援,因此根據這些標準實現REST服務具有較高的訊息自描述性。舉例來說,如果在請求中標明瞭If-Modified-Since頭,那麼服務端將可能返回一個304 Not Modified響應。在看到該響應的時候,瀏覽器或其它瀏覽工具可以從快取中取得上一次得到的結果。因此,在一個基於HTTP的REST系統中,如何準確地使用HTTP協議是一項非常重要的內容。

  在獲知瞭如何對響應所攜帶的負載進行解析之後,我們就來看看資源的自描述性。在上面的示例中,服務端響應使用了JSON表示了食品分類。該表示首先通過label屬性描述了自己是一個什麼分類。接下來,其通過brands屬性表示了該分類中的著名品牌,並通過hot_searches標示了在該分類中的熱搜關鍵字。可以看到,該負載中的所有屬性都清晰地描述了自身所表達的含義。

  那在該資源表示中的url屬性是什麼意思?實際上這是為子約束“每個資源都擁有一個資源標識”所新增的一個屬性。該子約束要求每個資源的資源標識可以用來唯一地標明該資源。對於網路應用來說,資源標識就是URI。而在一個基於HTTP的系統中,最自然的資源標示便是URL。在表示單個資源的時候,這個URL常常會包含著資源在該類資源中的ID。

  在本文的其它章節中,我們就將以這種方式來區分URL和ID:URL用來指向資源所在的地址,而ID則表示該資源在該型別資源中的ID。請讀者一定要記得這兩個術語所對應的不同意義,以防止理解錯誤。

  現在還有一部分食品分類表示中的屬性沒有被講解,那就是在該表示中的各個URL。這是為子約束HATEOAS服務的。在使用者看到items_url屬性時,其就可以通過向該URL傳送GET訊息得到屬於食品分類中的所有商品的列表。而在商品品牌的表示中也擁有一個url屬性。也就是說,向該URL傳送一個GET請求也能夠得到相應品牌的詳細資訊。

  您可能會問:既然在介紹HATEOAS時說REST服務並不需要文件來告訴使用者哪裡擁有什麼樣的資源,那使用者應該如何知道向/api/categories傳送GET請求就能得到所有的分類呢?標準的做法則是向/api直接傳送一個GET請求:

1 GET /api
2 Host: www.egoods.com
3 Authorization: Basic xxxxxxxxxxxxxxxxxxx
4 Accept: application/json

  而在返回的響應中將標示出REST API的版本以及所有可以訪問的資源等資訊:

複製程式碼
 1 HTTP/1.1 200 OK
 2 Content-Type: application/json
 3 Content-Length: xxx
 4 
 5 {
 6    "version": "1.0",
 7    "resources": [
 8       {
 9          "label" : "Categories",
10          "description" : "Product categories",
11          "uri": "/api/categories"
12       }, {
13          "label" : "Items",
14          "description" : "All items on sell",
15          "uri": "/api/items
            
           

相關推薦

REST架構風格簡介

http://www.cnblogs.com/loveis715/p/4669091.html   一說到REST,我想大家的第一反應就是“啊,就是那種前後臺通訊方式。”但是在要求詳細講述它所提出的各個約束,以及如何開始搭建REST服務時,卻很少有人能夠清晰

理解本真的REST架構風格

stack 事先 查找 增加 apple 是個 問題 等級 解答 本文是“深入探索REST”專欄系列深度內容中的第二篇,它將帶您領略REST架構的起源、與Web的關系、REST架構的本質及特性,以及REST架構與其他架構風格之間的比較。 引子 在移動互聯網、雲計算迅猛發展的

詳解REST架構風格

編輯推薦: 本文來自於segmentfault.com,一起了解REST的內在,認識REST的優勢,而不再將它當作是“理所當然”

REST架構風格架構元素

本文是筆者研究REST總結的第二篇。建議閱讀本文之前,先看一下筆者對REST總結的第一篇文章《REST架構風格的由來》,弄清楚REST的由來,再看本篇。 表述性狀態轉移(REST)風格是對分散式超媒體系統中的架構元素的一種抽象。REST忽略了元件實現和協議語法的細節

REST架構風格的由來

筆者聽到REST也有快兩個年頭了,但是就筆者而言,身邊的同事,朋友談論它的很多,但總感覺說的有些欠缺,聽的人也感覺迷迷糊糊的。包括筆者的資深架構師同事也對REST的理解感覺不是那麼的地道,都停留在一個模稜兩可的程度。如果要細究REST,誰也說不出個一二,這讓筆者感覺

基於Java的REST架構風格及介面安全性設計的討論

1.REST即表現層狀態傳遞(Representational [,rɛprɪzɛn'teʃnl] State Transfer,簡稱REST)。 (1)REST名詞解釋: 通俗來講就是資源在網路中以某種表現形式進行狀態轉移。分解開來: Resource:所指的不只

架構風格:你真的懂REST嗎?

本文探討如下幾個問題: 什麼是REST REST包含哪些約束 什麼是RESTful 純RESTful API的難點在哪裡 如果你去搜索「什麼是REST」的話,大部分情況下,你看到的基本都是RESTful! 這類內容主要說的是: 資源URL應該怎麼寫 要用GET來獲取資源 要用POST來新建資源 要用PU

SOA 服務架構簡介及理解

時代 底層原理 需要 松耦合 hit 面向服務 ges 都在 觀察 也許你已經深入其中卻不知,今天我們撥開雲霧見月明,闡明SOA是何方神聖! SOA 英文:Service-Oriented Architecture,面向服務的架構。 是一種面向通用集成服務的、松耦合的架構

領域驅動設計架構風格

des 設計 表達 對象 切入點 解決 基於 1.5 pattern 領域驅動設計 (DDD) 是面向對象的軟件設計方法,基於業務領域、元素和行為,以及它們之間的關系。其目標是將潛在業務領域的實現用業務領域專家語言定義的領域模型來表達出來。領域模型可以看一個框架,讓業務變得

REST架構與傳統MVC

ftw 處理 put 優化 interface 聯網 參數 優點 out 一前言 : 由於 REST 可以降低開發的復雜度,提高系統的可伸縮性,增強系統的可擴展性,簡化應用系統之間的集成,因而得到了廣大開發人員的喜愛,同時得到了業界廣

【DDD】領域驅動設計實踐 —— 架構風格架構實例

讀取 bili 邏輯 stat orcal ransac 應用服務 業務場景 解讀 概述 DDD為復雜軟件的設計提供了指導思想,其將易發生變化的業務核心域放置在限定上下文中,在確保核心域一致性和內聚性的基礎上,DDD可以被多種語言和多種技術框架實現,具體的框架實現需要根據

微信紅包的架構設計簡介

one next ext 均值 計數器 入庫 整理 余額 怎麽辦 @來源於QCon某高可用架構群整理,整理朱玉華。 背景:有某個朋友在朋友圈咨詢微信紅包的架構,於是乎有了下面的文字(有誤請提出,謝謝) 概況:2014年微信紅包使用數據庫硬抗整個流量,2015年使用cache

restful架構風格設計準則(五)用戶認證和session管理

好的 困難 是否 ica 過程 集成 設計 管理服務器 系統 讀書筆記,原文鏈接:http://www.cnblogs.com/loveis715/p/4669091.html,感謝作者! Authentication   其實在上一節中,我們已經提出了無狀態約束給REST

軟件架構,WEB - REST架構,RESTful API

clas www. present lock question pre sent 分享圖片 rest 參考 https://www.zhihu.com/question/27785028/answer/48096396 wiki太學術化了 http://www.ruan

什麼是REST架構?是不是Web應用都能採取此種架構呢?

REST架構風格是全新的針對Web應用的開發風格,是當今世界最成功的網際網路超媒體分散式系統架構,它使得人們真正理解了Http協議本來面貌。隨著 REST架構成為主流技術,一種全新的網際網路網路應用開發的思維方式開始流行。  REST是什麼  REST是英文Repre

淺談RESTful架構風格

RESTful REST (representation state transfer)表述性狀態轉移。該架構主張服務端維護資源狀態,客戶端維護會話狀態,消除服務端維護客戶請求狀態的開銷,有利於伺服器橫向擴充套件和負載均衡。 REST使伺服器處於無狀態,及伺服器僅僅管理資源的狀態

REST 程式設計風格是什麼

首先,REST規範: 強調HTTP應當以資源為中心,並且規範了資源URI的風格; 規範了HTTP請求動作(PUT,POST等)的使用,具有對應的語義; 遵循REST規範的網路應用將會獲得下面好處: URL具有很強可讀性的,具有自描述性; 資源描述與檢視的鬆耦合;

架構簡介

整理自網路   架構師 系統架構師是一個既需要掌控整體又需要洞悉區域性瓶頸並依據具體的業務場景給出解決方案的團隊領導型人物。一個架構師得需要足夠的想像力,能把各種目標需求進行不同維度的擴充套件,為目標客戶提供更為全面的需求清單。   架構師在軟體開發的整個過程

系統架構設計師-軟體水平考試(高階)-理論-架構風格

系統架構設計師-架構風格     前言: 看來非技術向的架構XMIND真的真的受歡迎啊。上一篇非技術類的閱讀量明顯高出平均水準好多。。。 但是,這次真的是系統架構師這個考試最有價值的技術類XMIND了。 如果感覺圖片模糊,請將圖片下載,或放大圖片。(圖片絕對清晰)  

系統架構設計師-軟件水平考試(高級)-理論-架構風格

兩種 它的 中間 而且 瓶頸 負責 回來 非功能需求 表現 系統架構設計師-架構風格 前言: 看來非技術向的架構XMIND真的真的受歡迎啊。上一篇非技術類的閱讀量明顯高出平均水準好多。。。 但是,這次真的是系統架構師這個考試最有價值的技術類XMIND了。 如果感覺圖片模糊,