本文是Horizon第二次線下活動中「RESTful Web」講題的總結,由PengEdy整理。前端
REST的全稱是Representational State Transfer,可譯爲「表徵狀態轉移」,是Roy Fielding博士在2000年他的博士論文中提出的一種軟件架構風格。目前,在三中主流的Web服務實現方式中,與SOA和RPC相比,REST的實現更爲簡潔,於是獲得愈來愈多的商業公司和開發者的青睞。git
本文將簡單介紹給讀者,如何理解REST、以及舉例說明在開發場景的簡單應用。程序員
在理解REST以前,先要對Web和Web Service有一個簡單的認識。編程
一切還要從互聯網誕生提及。互聯網從誕生至今,經歷了幾個發展階段:瀏覽器
階段一:靜態內容階段緩存
互聯網自己是爲歐美各高校/研究院共享信息而誕生的,在最初的那個年代,能訪問到的互聯網內容全都是文本內容(不少是於科研有關的論文、資料),所謂的Web服務器更像是一臺支持解析超文本的文件共享服務器。安全
階段二:CGI程序階段服務器
後來人們想在Web上加入更多的功能,而非原先簡單的超文本解析。這就須要Web服務器提供可用的API,經過程序與客戶端進行通訊,達到內容交互的做用。服務器與客戶端程序的通訊由CGI(通用網關接口)協議來完成,而這些用於通訊的程序就叫作CGI程序。網絡
階段三:腳本語言階段session
CGI程序有相對較高的安全隱患和開發難度。後來,在服務器端就出現了PHP、ASP、JSP等支持session的腳本語言,瀏覽器端也誕生了JavaScript、Java Applet,這大大下降了Web開發的難度,而互聯網上的內容與交互形式也變得更爲豐富。
階段四:Thin Client App階段
腳本語言易於開發,但大量的堆積卻不利於項目的維護,因此就有人提出了MVC開發模式,也就漸漸誕生了各種MVC開發框架。同時,也誕生了獨立於Web服務器的應用服務器,這就爲瘦客戶端應用提供了有力的發展條件。在這個階段裏,瘦客戶端再也不簡單的解析HTML、執行JavaScript,而是單獨執行其餘的程序代碼,從而提供了極爲豐富的人機交互方式。互聯網也變得更加精彩。
階段五:Rich Internet App階段
層出不窮的瘦客戶端技術令開發者頭暈目眩,而這時傳統的Web技術有了新的發展,給開發者提供了互聯網內容和交互形式均可兼得的選擇。這期間,以JavaScript爲核心的前端技術高速發展,誕生了Ajax、jQuery、ExtJs等模式與框架。這些技術一直到如今都煊赫一時。
階段六:Mobi App階段
iOS的誕生使移動互聯網爆發性增加,後來也有Android和Windows Phone加入,而從前的前端技術也同時顧及桌面端和移動端。原生移動平臺開發很受歡迎的同時,基於HTML5的開發技術也變得很流行。
從這個過程來看,Web變得愈來愈複雜;爲了支持這樣龐大的互聯網,背後的技術也在不斷更新。當CGI乃至服務器端腳本語言出現後,HTTP/1.0便沒法知足Web開發的要求,HTTP/1.1應運而生,其做者之一的Roy Fielding博士在HTTP/1.1的基礎上推導出了一種全新的軟件架構風格,也就是REST。
說到REST,就必須先對Web Service有一個基本的認識。
Web服務,直觀的認識能夠是「萬維網上的一套消息傳遞機制」;實際上,W3C組織給出了精準的定義:Web服務應帶是一個軟件系統,用以支持網絡間不一樣機器的互動操做,網絡服務一般是由許多API組成,它們經過網絡來執行客戶提交的各類請求。
看過這個較爲抽象的定義後,若是感受吃不消,能夠結合Web服務的使用方式來進一步理解。
Web服務有三種廣泛的實現方式,分別是:RPC,SOA,REST。
遠程過程調用(RPC)
這是一種早期的Web服務實現方式,最容易理解,要求Web服務提供一個分佈式函數或方法接口供用戶調用。就比如把一套系統的函數、方法(包含參數)提供給開發者(這樣作同時也會把部分信息暴露在開放的互聯網上)。
這裏給出一組例子,能夠感覺一下。
Server端
getUser(id) addUser(id, name) removeUser(id) updateUser(id, attr) getLocation(id) addLocation(id, Px, Py) removeLocation(id) updateLocation(id, Px, Py)
Client端
exampleAppObject = new ExampleApp("example.com:1234") exampleAppObject.getUser(id)
這樣作的弊端在於耦合性強和安全性差。當一套系統變得龐大時,組織合理的函數、方法接口將會變得很是繁瑣;並且接口和程序語言有必定的關聯,這樣也限制了開發者。
服務導向架構(SOA)
如今,業界關注的重點是聽從服務導向架構(Service-oriented Architecure)來構建的Web服務。在這種架構中,通信由消息驅動,而不是再由某個具體的動做(函數或方法調用)來實現。這種方式與RPC的最大區別是,更加關注如何去鏈接服務,而非關心特定細節的實現。關於SOA的更詳細的資料能夠查閱互聯網。
表徵狀態轉移(REST)
表徵狀態轉移類型的Web服務相似HTTP或其餘協議,它們以資源爲核心,把接口限定在一組廣爲人知的標準動做中(如GET, PUT, DELETE等),以供調用。這類Web服務與前面兩個相比,更加關注資源自己,而非消息或動做。
下面再給出一組例子。
Server端
http://example.com/users/ http://example.com/users/{user} http://example.com/findUserForm http://example.com/locations http://example.con/locations/{location} http://example.com/findLocationForm
Client端
userResource = new Resource("http://example.com:1234"") userResource.get(:id)
顯然,這種Web服務的方式並不受限於編程語言種類,組織龐大的URI也不是很繁瑣,並且以資源爲核心,以HTTP協議爲基礎,更便於在互聯網上傳播。
因此,如今的互聯網就是由各個Web服務構成的,從程序的角度來看,好像就是這樣。
但做爲普通網民,真的難以理解上面討論的內容,由於他們才無論什麼RPC/SOA/REST,他們只關心互聯網的內容。因此,咱們能夠拓寬對「Web服務」的理解,把Web服務看作是兩部分:
* 面向人類用戶的Web服務
也就是咱們打開瀏覽器、App所訪問的Web內容。
* 面向程序/程序員的Web服務
如上所說的一套軟件系統,最關鍵的是那組API。
因此,互聯網仍是由各種Web服務組成的,這就又回到了RESTful Web的話題上。
以上,能夠認爲:RESTful Web就是以HTTP/1.1爲基礎,以資源爲核心提供的現代Web服務,而「表徵狀態轉移」就做爲一種架構風格(或規範)存在,而非業界標準。
前面說的網站、Web服務,其實都是存在於生產環境中的分佈式Web系統。因此要想作到REST,咱們能夠假象有一個「初始化」的Web分佈式系統,給它加上約束條件,使之成爲RESTful的系統。
REST架構風格中最重要的架構約束有6個:
客戶-服務器
由客戶端發出「請求」,做爲通訊的開始,服務器進行「響應」。
無狀態
僅由客戶端負責維護通訊的會話狀態
緩存
響應的內容應該能夠在通訊鏈的某個環節被緩存,以改善網絡效率。
統一接口
「客戶端-服務器」通訊鏈組件之間應經過統一的軟件接口來實現通訊,從而提升交互的可見性。
分層系統
限制各組件的行爲,實現通訊鏈上下游分層。
按需代碼
支持下載並執行一些代碼(如JavaScript),對客戶端功能進行擴展。
這其中,第六個約束是可選特性,也就是說僅符合前五個約束的Web分佈式系統也能夠看作是知足REST設計風格的。
對於軟件架構師,能夠順着上面的思路,最終能推導出一套知足REST的軟件系統;而對於程序員,須要掌握符合REST規範的編程方法,不管是否使用支持REST的開發框架。
HTTP/1.1規範規定了八個動詞:OPTION, HEAD, GET, POST, PUT, DELETE, TRACE, CONNECT
,分別表明了不一樣的語義,其中GET, PUT, POST, DELETE
就是CRUD的語義化動詞,在開發Web系統中很是經常使用。
強調規範使用這些動詞,是由於有不規範的狀況出現。好比GET
,做爲一個安全動詞,本來是用於發出查找請求。下面有兩個很差的例子:
# Add cart GET /add_cart?pid=1234 HTTP/1.1 Host: www.example.org # Delete note GET /notes/delete?id=1234 HTTP/1.1 Host: www.example.org
原本是用於請求查詢的報文卻在請求增長/減小資源。這樣寫的程序能夠執行,但有很是大的隱患,有可能在未知的狀況下形成數據的大量變更,好比一些緩存程序或惡意攻擊。
資源能夠看作是一個Web系統的核心,由於不論業務邏輯怎麼複雜,都是對數據進行增刪改查。但資源不一樣於數據,資源要有名稱,並且是能夠在萬維網上能夠定位到資源自己的名稱——也就是URI(Uniform Resource Identifier)。因此資源命名就尤其重要,以知足易於編程和用戶可讀爲標準。看下面這些例子,就能體會到。
POST http://example.com/customers GET http://example.com/customers/123 DELETE http://example.com/products/123 PUT http://example.com/customers/123/orders/45
真實的互聯網還有更多形象的例子,它們那樣良好的命名設計使得不管是普通用戶仍是開發人員都能更方便地在網上完成相關業務,這也是REST優點的一點體現。
狀態響應碼是HTTP協議中規定的一部分。協議中規定了不少組數字,用來表示網絡中可能發生的最多見的狀況。若是須要開發Web系統的API,那麼就須要按照HTTP報文的要求,爲響應報文中提供準確的響應代碼,以區分相關請求的執行狀態。
好比在客戶端執行了某個GET
請求,API一般須要返回200,表示請求成功,其餘狀況則按照須要返回40三、40四、405等。
這裏列出幾個經常使用的響應碼:
是的,關於REST還有很是多的內容,但本文到這裏就要告一段落了,而想要深刻了解REST的特性,乃至構建本身的RESTful Web系統,到此爲止是遠遠不夠的。
目前的主流編程語言,如Java、PHP、Python、Ruby、Node.js、C#等,都已經實現了各自的支持REST的編程框架,能夠根據興趣選擇其中之一來學習並實踐。
這裏還有重要的閱讀資料,以便深刻研究REST架構範式: