1. 使用ASP.NET Core 3.x 構建 RESTful API - 1.準備工做javascript
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。 html
REST的全稱是 Representational State Transfer(狀態表述轉換)。這個詞表面看起來可能不太好理解。但其實REST就是勾畫出了這樣一幅景象,它描述了Web應用到底怎麼樣設計纔算是優良的。這裏定義瞭如下三點: java
一組網頁的網絡(一個虛擬狀態機); json
在這些網頁上,用戶能夠經過點擊連接來前進(狀態轉換); api
點擊連接的結果就是下一個網頁(表示程序的下一個狀態)被傳輸到用戶那裏,並渲染好給用戶使用。 瀏覽器
論文中還提到,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,3,4共四個級別。咱們一個一個看。
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。