天天看點

使用ASP.NET Core 3.x 建構 RESTful API - 2. 什麼是RESTful API

1. 使用ASP.NET Core 3.x 建構 RESTful API - 1.準備工作

REST一詞最早是在2000年,由Roy Fielding在他的博士論文《Architectural Styles and the Design of Network-based Software Architecture》中提出的。他在本文中創造了REST這個術語。這篇論文的位址是:https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm。 

REST的全稱是 Representational State Transfer(狀态表述轉換)。這個詞表面看起來可能不太好了解。但其實REST就是勾畫出了這樣一幅景象,它描述了Web應用到底怎麼樣設計才算是優良的。這裡定義了以下三點: 

一組網頁的網絡(一個虛拟狀态機); 

在這些網頁上,使用者可以通過點選連結來前進(狀态轉換); 

點選連結的結果就是下一個網頁(表示程式的下一個狀态)被傳輸到使用者那裡,并渲染好給使用者使用。 

論文中還提到,REST是一種為分布式超媒體系統所用的架構風格,也就是說,REST定義了一種架構風格來幫助建立群組織出更好的分布式系統。這裡的關鍵詞是架構風格。 

概括的說: 

REST是一種架構風格,而不是規範或标準; 

REST需要使用一些規範、協定或标準來實作這種架構風格; 

REST與協定無關。JSON并不是REST強制的,甚至HTTP都不是REST強制使用的,但這也僅僅是從理論上來看。 

REST背後的主要思想就是:采用RESTful架構風格進行組織的分布式系統,将在以下幾個方面得到改善: 

性能。REST的通信風格應該是簡單并且高效的,采用它的系統性能應該得以提升。 

元件互動的可擴充性。其實任何分布式系統都允許這種擴充性,而REST所提出的簡單互動方式更是如此。 

元件的可修改性。分布式系統的分布式本質和REST提出的關注點分離,使得元件得以以最小的成本和最低的風險彼此獨立的進行修改。 

可移植性。REST與技術和語言無關,是以使用任何技術都可以實作REST。 

可靠性。REST所提出的無狀态限制允許在系統發生故障後輕松的恢複系統。 

可視性。REST所提出的無狀态限制為所述請求添加了完整的狀态(一會再解釋)。 

從上面這個清單,我們可以看出,一個以元件為中心設計的系統非常容易出錯,如果一個元件出現了故障而不影響整個系統的穩定性,那這樣對任何系統都是極有好處的。對元件進行互聯是非常簡單的,但是需要在添加新特性或擴大縮小規模時将風險降至最低。憑借REST的可移植性,使用REST思想進行設計的系統可以為更廣泛的閱聽人使用。通過通用的接口,系統可以被更廣泛的開發者所使用。為了實作這些屬性和好處,REST使用一組限制來幫助定義統一的接口。 

為了定義REST架構,首先要定義出一個空無的狀态,也就是一個沒有任何限制的系統。在這裡,元件之間的差異就是個迷,然後我們再一個挨一個的往裡面添加限制并保證這些限制可以互不幹擾、融洽相處。這些限制都定義了實作REST API的架構應該如何被建構和設計。下面就介紹一些這六個限制: 

用戶端-伺服器:關注點分離是這個限制的核心主題。整個Web系統是一個基于用戶端-服務端的系統,用戶端和服務端彼此獨立(獨立實作和部署等),并扮演着不同的角色。它們可以使用不同的語言、技術或平台,并可以獨自進化,隻要它們都遵從Web的統一接口即可。 

無狀态:無狀态表示Web伺服器不被要求記住用戶端程式的狀态,因為這個原因,用戶端在發送請求的時候必須包含所有可能需要的相關資訊,也就是說狀态需要被包含在請求裡,同時也說明用戶端需要維護自己的狀态。由于維護狀态的工作由用戶端自己來完成了,是以伺服器就節省了很多伺服器資源,這樣伺服器就可以為更多的用戶端服務。 

統一的資源接口/界面:Web元件之間的互動就意味着用戶端、服務端以及基于網絡的中介程式都依賴于它們接口的統一性(API和API的消費者之間共用相同标準的一套接口)。Web元件可以在統一接口的四個限制條件下一緻的進行互操作。這四個限制是: 

資源的辨別:針對RESTful Web API而言,就是指URI,隻有得到這個資源辨別,才有可能找到該資源并對該資源進行操作。但是從概念上來講,資源和它的表述是分開的。例如,我們通過一個URI找到了服務端的Company這個資源,但是我們得到的Company這個資源的表述和服務端的Company是不一樣的,因為我們得到的是JSON格式(大多數情況)的Company資料。同時還有媒體類型(media type)對其進行描述,例如application/json等。如果請求的是xml格式的資料,那麼我們通常會得到xml格式表述的資料。是以同一個資源得到的表述也可能是不同的(例如JSON vs Xml)。 

通過表述來對資源進行操縱:REST的元件對資源的操作(CRUD)是通過首先擷取該資源現有的表述或者目标表述,然後在元件之間完成從現有表述到目标表述的轉換。換句話講,當用戶端擁有資源表述的時候(包括可能的中繼資料),那麼它就應該擁有足夠的資訊來修改或者删除伺服器上的資源,前提是用戶端需要有這些權限。例如,我從伺服器擷取到了Company的資源響應(包括中繼資料)之後,憑借這些資訊用戶端就應該可以成功的删除或修改這個Company的資源資料了。但這又是怎麼實作的呢?如果伺服器上的Company API支援對Company進行删除或者修改,那麼在我們擷取(GET)到這個Company資源的響應後,響應裡面應該包含着删除或者修改這個Company資源的URI,通過這些URI用戶端就可以完成相應的操作。 

帶有自我描述的資訊:由于REST是無狀态的(沒有會話機制),是以發送REST請求的時候,必須把所有相關的資訊随着請求一起發送到伺服器端。換句話說,需要通過使用中繼資料或者其它方式,讓REST的請求中包含的資料必須帶有“自我描述”性的資訊,以便讓對方知道如何處理該請求。 

超媒體作為應用程式狀态的引擎(HATEOAS):REST架構風格中,用戶端是通過超媒體與伺服器端動态提供的一個“應用網絡”來進行互動的。這裡要求在首次進入REST網絡時有第一個連結,還要求用戶端必須具備處理超媒體内容的能力。除此之外REST對用戶端來說再無其它要求。這是書上給出的解釋。舉個例子,本文第二段中提到使用者通過點選網頁中的連結來進行跳轉的時候,浏覽器的狀态就變化了。這些連結就是超文本,而超媒體就是超文本的泛化。針對API來說,它就是程式狀态的引擎。換句話說,超媒體會驅動如何消費和使用API,它會告訴API消費者使用這些API能做什麼,例如:能删除這個資源嗎?能修改資源嗎?如何能建立這種資源?從哪能擷取這個資源?最終,它還允許自包含文檔的API。 

多層系統:REST的解決方案适用于多層架構,這些層可以被修改,可以被添加或删除,可以是實體的,也可以是邏輯的。每一層隻可以看到和它相鄰的上一層或下一層,其它非相鄰層的結構它完全看不到。這也說明用戶端無法得知它連接配接的是架構最終層還是連接配接到了某個中間層。是以REST僅僅知道一個層,也就是對外那一層,因為這個原因,整個系統的複雜性得到了控制,因為可以對任何局部的層次進行替換,而不至于影響整個系統。 

可緩存:每個響應資訊必須明确的指出它是否可以被緩存。緩存響應資料可以減少用戶端感覺的響應時間,提高整體的可用性和可靠性,并控制整個Web伺服器的負載。用戶端也可以在實時性和響應速度之間做出選擇,以便伺服器端相應的決定是從緩存還是從最終資訊源哪裡獲得服務響應的内容。 

按需編碼(可選限制):它描述了伺服器可以擴充或者定制用戶端的功能。例如如果用戶端是一個Web應用,那麼伺服器端可以發送一些javascript腳本給用戶端,以擴充用戶端的功能。但是這也造成了用戶端和伺服器端之間的技術耦合,因為用戶端必須能都懂得伺服器端發過來的代碼,是以這個限制是可選的。 

這些就是REST的限制,而沒有實作這些限制的Web API就不是RESTful API,是以現在見到的很多RESTful API并不是真的RESTful API,但是這也不能說明這些API就不好,隻不過針對那些沒有實作的限制可能要做出一些權衡取舍,付出一些代價。 

這個成熟度模型是由Leonard Richardson所提出的,這個模型是用來評價API的成熟度。它的結果分為0,1,2,3共四個級别。我們一個一個看。 

Level 0,POX(Plain old xml)沼澤。它描述了API僅僅是使用HTTP協定來做遠端互動,而HTTP協定的其餘部分都是瞎用的,有時用出了RPC的風格(例如SOAP, 尤其是使用WCF的時候)。例如下面這個程式都是在同一個URI上面進行讀取資源和建立資源的: 

換句話說,就是使用HTTP協定作為一種傳輸方式而已,沒有什麼規矩可言。 

Level 1,資源。在這級裡, 與Level 0不同,每個資源都映射到自己的URI上了, 但是HTTP方法并沒有正确的使用, 但是還是降低了一些複雜度。例如下面這個例子使用了不同的URI,但是HTTP方法使用的都是POST: 

Level 2,動詞。正确使用了HTTP動詞,例如GET、POST、DELETE、PUT、PATCH等等都是按照協定的意圖正确的使用了。狀态碼也正确的使用了,例如200表示成功,201表示建立成功等等。這也符合了統一資源接口/界面這個限制。從軟體開發角度,這也去掉了不必要的變種,因為我們使用同樣的動詞來做同類的事情。例如: 

Level 3,超媒體。這意味着,API支援HATEOAS(超媒體作為應用狀态的引擎, Hypermedia as the Engine of Application State),這也是統一資源接口/界面限制裡面的一條。例如: 

這個GET請求的響應除了包含資料之外,還包含連結(超媒體),這些連結可以驅動應用程式的狀态。從軟體開發的角度講,就是引入了可發現性和自包含文檔。 

根據Roy Fielding博士的描述,達到Level 3也僅僅是RESTful API的一個前提。也就是說隻有你的API達到了Level 3水準之後,才可以談論你的API是不是RESTful API。 

使用ASP.NET Core 3.x 建構 RESTful API - 2. 什麼是RESTful API