2000年,Roy Thomas Fielding博士在他那篇著名的博士論文《Architectural Styles and the Design of Network-based Software Architectures》中提出了幾種軟件應用的架構風格,REST做爲其中的一種架構風格在這篇論文的第5章中進行了歸納性的介紹。html
REST是「REpresentational State Transfer」的縮寫,能夠翻譯成「表現狀態轉換」,可是在絕大多數場合中咱們只說REST或者RESTful。web
Fielding在論文中將REST定位爲「分佈式超媒體應用(Distributed Hypermedia System)」的架構風格,它在文中提到一個名爲「HATEOAS(Hypermedia as the engine of application state)」的概念。api
SOAP Web API採用RPC風格,它採用面向功能的架構,因此咱們在設計SOAP Web API的時候首相考慮的是應高提供怎樣的功能(或者操做)。安全
RESTful Web API採用面向資源的架構,因此在設計之初首先須要考慮的是有哪些資源可供操做。服務器
一個資源必須具備一個或者多個標識,既然咱們設計的Web API,那麼很天然地應該採用URI來做爲資源的標識。restful
除了必要的標誌性和可選的可讀性以外,標識資源的URI應該具備「可尋址性(Addressability)」。數據結構
URI不只僅指明瞭被標識資源所在的位置,並且經過這個URI能夠直接獲取目標資源。架構
在絕大多數狀況下,資源並不會孤立地存在,必然與其它資源具備某種關聯。app
利用URL將資源關聯在一塊兒,就是一份超文本/超媒體文檔,咱們能夠根據須要獲取對應的資源,這也是爬蟲的實現原理。負載均衡
Fielding在他的論文中將REST定位爲「分佈式超媒體應用」的架構風格,而超媒體的核心就是利用「連接」相關的信息結成一個非線性的網,因此從一點也能夠看出REST和「使用連接關聯相關的資源」這個特性使吻合的。
可否採用統一接口是RESTful Web API和採用RPC風格的SOAP Web服務又一區別。
#RPC風格
1: public class RoleService 2: { 3: public IEnumerable<string> GetAllRoles(); 4: public void CreateRole(string roleName); 5: public void DeleteRole(string roleName);
6: public void AddRolesInUser(string userName, string[] roleNames); 7: public void RemoveRolesFromUser(string userName, string[] roleNames); 8: }
#RESTful 1: public class RolesService 2: { 3: public IEnumerable<string> Get(); 4: public void Create(string roleName); 5: public void Delete(string roleName); 6: } 7: 8: public class RoleAssignmentsService 9: { 10: public void Create(RoleAssignment roleName); 11: public void Delete(RoleAssignment roleName); 12: }
Web API分別針對CRUD的操做只能接受具備對應HTTP方法的請求.
GET、HEAD和OPTIONS這三個HTTP方法旨在發送請求以或者所需的信息。
OPTIONS請求旨在發送一種「探測」請求以肯定針對某個目標地址的請求必須具備怎樣的約束(好比應該採用怎樣的HTTP方法以及自定義的請求報頭),而後根據其約束髮送真正的請求。
POST、PUT、PATCH和DELETE,它們旨在針對目標資源做添加、修改和刪除操做。
經過發送POST和PUT請求都可以添加一個新的資源,可是二者的不一樣之處在於:
對於前者,請求着通常不能肯定標識添加資源最終採用的URI,即服務端最終爲成功添加的資源指定URI;
對於後者,最終標識添加資源的URI是能夠由請求者控制的。
也正是由於這個緣由,若是發送PUT請求,咱們通常直接將標識添加資源的URI做爲請求的URI;
對於POST請求來講,其URI通常是標識添加資源存放容器的URI。
關於HTTP請求採用的這些個方法,具備兩個基本的特性,即「安全性」和「冪等性」。
GET、HEAD和OPTIONS均被認爲是安全的方法,由於它們旨在實現對數據的獲取,並不具備「邊界效應(Side Effect)」。
至於其它4個HTTP方法,因爲它們會致使服務端資源的變化,因此被認爲是不安全的方法。
冪等性(Idempotent)是一個數學上的概念,在這裏表示發送一次和屢次請求引發的邊界效應是一致的。
上述3種安全的HTTP方法(GET、HEAD和OPTIONS)均是冪等方法。
對於PUT請求,只有在對應資源不存在的狀況下服務器纔會進行添加操做,不然只做修改操做,因此它也是冪等方法。
至於最後一種POST,因爲它老是進行添加操做,若是服務器接收到兩次相同的POST操做,將致使兩個相同的資源被建立,因此這是一個非冪等的方法。
當咱們在設計Web API的時候,應該儘可能根據請求HTTP方法的冪等型來決定處理的邏輯。
資源和資源的表示(Representaion)是兩個不一樣的概念,資源自己是一個抽象的概念,是看不見摸不着的,而看得見摸得着的是資源的表現。
對於Web來講,目前具備兩種主流的數據結構,XML和JSON,它們也是資源的兩種主要的呈現方式。
咱們在設計Web API的時候,應該支持不一樣的資源表示,咱們不能假定請求提供的資源必定表示成XML,也不能老是以JSON格式返回獲取的資源,正確的作法是:根據請求攜帶的信息識別提交和但願返回的資源表示。
對於請求提交的資源,咱們通常利用請求的Content-Type報頭攜帶的媒體類型來判斷其採用的表示類型。
對於響應資源表示類型的識別,能夠採用以下兩種方式:
1.讓請求URI包含資源表示類型,這種方式使用的最多的是針對多語言的資源,咱們通常講表示語言(也能夠包含地區)的代碼做爲URI的一部分,好比「http://www.artech.com/en/orders/2013」表示將2013年的訂單以英文的形式返回。
2.採用「內容協商(Content Negotiation)」根據請求相關報頭來判斷它所但願的資源表示類型,好比「Accept」和「Accept-language」報頭能夠體現請求能夠接受的響應媒體類型和語言。
RESTful只要維護資源的狀態,而不須要維護客戶端的狀態。
對於它來講,每次請求都是全新的,它只須要針對本次請求做相應的操做,不須要將本次請求的相關信息記錄下來以便用於後續來自相同客戶端請求的處理。
通常狀況下,頁面導航均具備「上一頁」和「下一頁」連接用於呈現當前頁的前一頁和後一頁的記錄。
那麼如今有兩種實現方式返回上下頁的記錄:
1.Web API不只僅會定義根據具體頁碼的數據查詢定義相關的操做,還會針對「上一頁」和「下一頁」這樣的請求定義單獨的操做。
它自身會根據客戶端的Session ID對每次數據返回的頁面在本地進行保存,以便可以知道上一頁和下一頁具體是哪一頁。
2.Web API只會定義根據具體頁碼的數據查詢定義相關的操做,當前返回數據的頁碼由客戶端來維護。
第一種貌似很「智能」,其實就是一種多此一舉的做法,由於它破壞了Web API的無狀態性。
設計無狀態的Web API不只僅使Web API自身顯得簡單而精煉,還因減除了針對客戶端的「親和度(Affinty)」使咱們能夠有效地實施負載均衡,由於只有這樣集羣中的每一臺服務器對於每一個客戶端纔是等效的。