天天看點

RESTful API命名實踐引言REST 的誕生REST 詳解REST 風格優點REST實踐體會

文章目錄

  • 引言
  • REST 的誕生
    • Web 技術發展
    • REST 的誕生
  • REST 詳解
    • REST 架構風格
    • 解讀 REST
      • 1. 資源(Resources)
      • 2. 表現層(Representation)
      • 3. 狀态轉化(State Transfer)
      • 4. 綜述
    • REST 與 RESTful
  • REST 風格優點
  • REST實踐體會
    • 1. URI命名難度變大
    • 2. 用不用HTTP PATCH

引言

在網際網路高度普及的今天,作為一名Web開發者,如果你還沒聽說過“REST”這個技術名詞,出門都不好意思跟人打招呼。盡管如此,對于REST這個泊來品的了解,大多數人仍然停留在“盲人摸象”的階段。

有人認為,在Web Controller層寫的API就是REST API。而且,從開發角度對于URI的命名、HTTP Mehthod的選擇沒有建立起規範的意識。這樣是不優雅的!(沒有對錯之分)

作為帶着問題學習總結的我,未打算通過本篇文檔全面的闡述清楚REST,而是盡量的總結一些理論和思考,一起探讨!

REST 的誕生

Web 技術發展

Web開發技術的發展可以粗略劃分成以下幾個階段:

  1. 靜态内容階段:在這個最初的階段,使用Web的主要是一些研究機構。Web由大量的靜态HTML文檔組成,其中大多是一些學術論文。Web伺服器可以被看作是支援超文本的共享檔案伺服器。
    • 可以想象下當時的HTTP請求隻有“GET”,且MIME為“HTML或TEXT”
  2. CGI程式階段:在這個階段,Web伺服器增加了一些程式設計API。通過這些API編寫的應用程式,可以向用戶端提供一些動态變化的内容。Web伺服器與應用程式之間的通信,通過CGI(Common Gateway Interface)協定完成,應用程式被稱作CGI程式。
  3. 腳本語言階段:在這個階段,伺服器端出現了ASP、PHP、JSP、ColdFusion等支援session的腳本語言技術,浏覽器端出現了Java Applet、JavaScript等技術。使用這些技術,可以提供更加豐富的動态内容。
  4. 瘦用戶端應用階段:在這個階段,在伺服器端出現了獨立于Web伺服器的應用伺服器。同時出現了Web MVC開發模式,各種Web MVC開發架構逐漸流行,并且占據了統治地位。基于這些架構開發的Web應用,通常都是瘦用戶端應用,因為它們是在伺服器端生成全部的動态内容。
  5. RIA應用階段:在這個階段,出現了多種RIA(Rich Internet Application)技術,大幅改善了Web應用的使用者體驗。應用最為廣泛的RIA技術是DHTML+Ajax。Ajax技術支援在不重新整理頁面的情況下動态更新頁面中的局部内容。同時誕生了大量的Web前端DHTML開發庫,例如Prototype、Dojo、ExtJS、jQuery/jQuery UI等等,很多開發庫都支援單頁面應用(Single Page Application)的開發。其他的RIA技術還有Adobe公司的Flex、微軟公司的Silverlight、Sun公司的JavaFX(現在為Oracle公司所有)等等。
  6. 移動Web應用階段:在這個階段,出現了大量面向移動裝置的Web應用開發技術。除了Android、iOS、Windows Phone等作業系統平台原生的開發技術之外,基于HTML5的開發技術也變得非常流行。

REST 的誕生

從上述Web開發技術的發展過程看,Web從最初其設計者所構思的主要支援靜态文檔的階段,逐漸變得越來越動态化。Web應用的互動模式,變得越來越複雜:從靜态文檔發展到以内容為主的門戶網站、電子商務網站、搜尋引擎、社交網站,再到以娛樂為主的大型多人線上遊戲、手機遊戲。

Web發展到了1995年,在CGI、ASP等技術出現之後,沿用了多年、主要面向靜态文檔的HTTP/1.0協定已經無法滿足Web應用的開發需求,是以需要設計新版本的HTTP協定。在HTTP/1.0協定專家組之中,有一位年輕人脫穎而出,顯示出了不凡的洞察力,後來他成為了HTTP/1.1協定專家組的負責人。這位年輕人就是Apache HTTP伺服器的核心開發者Roy Fielding,他還是Apache軟體基金會的合作創始人。

是以,REST 并不是在網際網路誕生之初就有的,它是在HTTP/1.1協定中才出現的,由Roy Thomas Fielding這位大神對Web技術做了深入的總結和分析,提出的一套網絡軟體的架構風格理論架構,當時Fielding為這種架構風格取了一個輕松愉快的名字:“REST” ———— Representational State Transfer(表述性狀态轉移)

  • Roy Thomas Fielding 關于REST的論文
    • https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf

REST 詳解

REST 架構風格

問題:REST 究竟是什麼?是一種新的技術、一種新的架構、還是一種新的規範?
           

首先,REST是Web自身的

架構風格

,也是世界上最成功的分布式應用架構風格。它是為運作在網際網路環境的分布式超媒體系統量身定制的。

  • REST是一種架構風格!
  • REST是一種架構風格!
  • REST是一種架構風格!

是以,就會存在實際開發工作中即使沒有正确的了解和應用REST,但也能順利的完成開發工作。也正因為如此,給開發工作中推廣正确實踐和統一風格帶來不小的困難。因為大多數程式員總是在尋找最快解決問題,最快完成需求的方式,怎麼簡單怎麼來。

解讀 REST

REST ———— Representational State Transfer (表現層狀态轉化)
           

從“Representational State Transfer”這個定義去了解REST架構風格原則。

1. 資源(Resources)

REST 的名稱“表現層狀态轉化”中,省略了主語。“表現層”其實指的是“資源(Resources)”的“表現層”

資源是一種看待伺服器的方式,此處指的“資源”是一個抽象的概念,它不僅僅指伺服器端真實存在的檔案、資料庫表,而是指任何可被名詞表述的東西。是以在定義“資源”時可以要多抽象就多抽象。

對于用戶端,可以将伺服器端看作是由很多離散的資源組成。服務端可以用URI(統一資源定位符)指向資源,每種資源都對應一個特定的URI。要向擷取這個資源,通路它的URI就可以了,是以URI就成了每一個資源的位址或獨一無二的識别符。

所謂“上網”,就是與網際網路上一系列的“資源”互動,調用它的URI。

2. 表現層(Representation)

"資源"是一種資訊實體,它可以有多在的表現形式。我們把“資源”具體呈現出來的形式,叫做它的“表現層(Representation)”

比如,文本資訊可以用txt格式表現,也可以用HTML格式 、XML格式、JSON格式表現,甚至可以用二進制格式;圖檔可以用JPG格式表現,也可以用PNG格式表現。

URI隻代表資源的實體,不代表它的表現形式。資源的具體表現形式,應該在HTTP請求的的頭部資訊中用Accept和Content-Type字段指明,這兩個字段才是對“表現層”的描述。

  • 詳見HTTP MIME明細

3. 狀态轉化(State Transfer)

HTTP協定是一個無狀态的協定,這意味着所有資源的狀态都儲存在伺服器端。因為用戶端想要操作伺服器,必須通過某種手段,讓伺服器端資源發生“狀态轉化”。而這種轉化是建立在表現層之上的,是以就是“表現層狀态轉化”。

用戶端用到的手段,隻能是HTTP協定。具體對應HTTP協定中的HTTP Method:GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS。每一種HTTP Method代表資源狀态轉化的一種

約定的

方式。

HTTP 動詞

對于資源的具體操作類型,有HTTP動詞表示。

常用的HTTP動詞如下:

- GET : 從伺服器取出資源(一個或多個)

- POST : 在伺服器建立一個資源,并傳回建立後的完整資源到用戶端

- PUT : 在伺服器以覆寫形式,全量更新資源,并傳回更新後的完整資源到用戶端

- PATCH : 在伺服器端更新資源,但隻更新指定的内容

- DELETE : 在伺服器端删除資源
           

其中,GET、PUT、PATCH、DELETE都應該是幂等的。

另外,HEAD、OPTIONS對于團隊開發來說基本不用。

- HEAD : 擷取資源的中繼資料

- OPTIONS : 擷取資訊,關于資源的哪些屬性是用戶端可以改變的
           

4. 綜述

綜合上面的解讀,總結一下什麼是REST架構風格:

(1) 伺服器端的任何資訊和資料都要被抽象資源化;

(2) 資源用URI進行表述,每一個URI代表一種資源;

(3) 用戶端與伺服器之間,基于某種表現層形式,互相傳遞資源;

(4) 用戶端與伺服器之間,基于HTTP Method對伺服器端資源的操作,實作“表現層狀态轉化”;

REST 與 RESTful

定義:

  • 如果一個架構符合REST原則,就稱它為RESTful架構
  • 如果HTTP API的設計符合REST原則,那麼可稱它為RESTful API

是以,回到開篇講的大多數人對于REST還是處于“盲人摸象”的階段,回想下自己和身邊的同僚,在工作中經常交流到的REST API或RESTful API,其實隻能算個HTTP API吧?

REST 風格優點

架構風格不是非此即彼的是非題,在實際開發中可以自主的選擇是否應用REST風格。那麼,如果應用REST風格會帶來哪些優勢呢?

  1. 從面向操作程式設計,轉變為面向資源程式設計。更面向對象,架構更清晰、松耦合。
    • 我們應該确定的認為系統由“資源+對資源的操作”組成,而不是由“操作”組成
    • 面向操作程式設計會導緻API膨脹,功能重複度高。
  2. 統一URI命名風格,URI具備很強的可讀性,具備自解釋的能力。伺服器資源層次目錄清晰。
  3. 狀态無關。確定系統橫向擴充的能力。
  4. 超文本驅動。確定系統演化的能力。

REST實踐體會

1. URI命名難度變大

在沒有要求URI必須用資源名詞來組成URI時,URI的命名從來不是什麼難事,常見的命名風格有:

  • 動詞+名詞
    • /deposit/getUsers: 擷取某個項目保證金使用者清單
    • /orders/submitAudit: 訂單送出稽核
    • /cart/add: 商品加購物車
  • URI全局唯一即可
    • /finance/budget/getPurchaseplanNextAuditOrgList:我有點小無語…
為什麼會這樣:

我們平時搞系統是這樣的:

  1. 有建立使用者功能
  2. 建立使用者需要一個URL
  3. 往這個URL發送的資料要定義好
  4. 開始寫後端和前端

這是以操作為第一位的設計方法,首先确認了一個操作,然後圍繞這個操作把周邊需要的東西建設好,這種方式當然可以架構出一個系統,甚至是一個好系統,但是偶爾會有些問題:

  1. 操作之間是會有關聯,你的設計容易變成“第2個操作要求第1個操作進行過”,這種關系多起來你的系統就亂了
  2. 你的URL設計會缺乏一緻性
  3. 操作通常被認為是有副作用(Side Effect)的,是以很少有人基于操作去設計緩存之類的東西
該怎麼應對?

确實,REST是高度抽象的理論和風格,在實際開發中會面對各種複雜的功能和場景,導緻很難完全的應用REST風格。當我們在争論REST風格到底如何設計才是正宗時,發現心中的困惑不僅沒有降低,反而增加了。

我的想法:仍以真正的系統需求為出發點,使用REST風格讓系統的架構更清晰,讓系統的開發協作更高效。部分不适合REST的場景應該靈活變通。

回到URI的命名:

  1. 堅持URI仍以資源為導向,清晰的表述伺服器端資源目錄
  2. 保障URI資源層次清晰的情況下,隻允許在URI最末一級添加動詞,例如:/market/orders/1/audit
  3. 如果某些動作是HTTP動詞表示不了的,考慮把動作抽象成一種資源

比如:網上彙款,從賬戶1向賬戶2彙款100元,錯誤的URI

POST /accounts/1/transfer/500/to/2
           

正确的寫法是把動詞transfer改成名詞transaction

POST /transaction?from=1&to=2&amount=100
           

2. 用不用HTTP PATCH

PATCH 作為HTTP的Method之一,其實它是2010年3月份才正式成為HTTP Method的,詳見:RFC 5789

也正因為PATCH出現的晚, 是以并不是所有Web容器都支援,反而目前實作了PATCH方法的Web容器很少

幾個常見Web容器實作PATCH方法的情況,供參考:

  1. Apache HttpComponents HttpClient version 4.2 or later 支援了 PATCH
  2. 目前 JDK7 的 HttpURLConnection 未實作 PATCH
  3. TOMCAT 7 也不行
  4. PlayFramework 2 也不支援
  5. Spring 3.2 開始支援 PATCH 方法,但要選對部署的容器
  6. JBoss Netty 支援 PATCH,可見: http://docs.jboss.org/netty/3.2/api/org/jboss/netty/handler/codec/http/class-use/HttpMethod.html