應用之間的通信可使用Web Services,也可使用REST(表述性狀態轉移),後者由於輕量級和優雅而頗受歡迎,REST基於Http,實際上就是一套對HTTP/URI的最佳實踐套路。在設計應用時能堅持REST原則,那就預示着你將會獲得一個使用了優質架構的系統。git
使用REST,套路分解爲五條原則:github
爲資源定義IDjson
充分使用ID來作連接瀏覽器
使用標準動詞緩存
資源能夠有多重表達形式安全
無狀態服務器
從需求文本中提取名詞和動詞是一條設計的捷徑。好比在電子商務應用中的一段需求描述:「客戶能夠點擊列表內的訂單,查詢得到此訂單」。那麼訂單(order)就是一個名詞。定義ID也就是讓每一個訂單能夠有一個ID來標識它。使用REST,標識的方式是這樣的:架構
http://example.com/order/1 http://example.com/order/2
分別代表查詢1號訂單、2號訂單。相似的,對於客戶、商品,能夠如此表達:app
http://example.com/customer/1234 http://example.com/product/4554
哦我去,那不是等於這玩意嗎:curl
class OrderManager{ Order get(id:integer); } OrderManager.get(1)
並且前面還多了一個方案(http://)和主機(example.com) ,好囉嗦。然而,好處就體如今這個囉嗦裏面了:
利用已被定義,現成的方案,易於理解的規則。
在全球範圍中一直在運行的。你的訂單能夠來自example.com,或者其餘叫作foo.com,bar.com之類的鏡像站上,它們可能分佈到全球各地。
利用現有的工具。好比訂單的連接能夠被多種渠道分享到朋友那裏,或者加入到瀏覽器的書籤中
處理單數名詞外,還有複數的,就是一組資源,相似這樣的:
http://example.com/orders/2007/11 http://example.com/products?color=green
對一類事物集合的標識。
連接是咱們在HTML中常見的概念,但還能夠更加通用。以下XML片斷把對應order的product和customer連接進來:
<order self="http://example.com/customers/1234"> <amount>23</amount> <product ref="http://example.com/products/4554"> <customer ref="http://example.com/customers/1234"> </customer> </product> </order>
應用程序能夠由此XML「跟隨」連接檢索product和customer的更多數據。
還能夠經過連接加入對資源的動做。好比你的帳戶還有100美圓的狀況下,你能夠作存款取款轉帳四個操做:
GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK <?xml version="1.0"?> <account> <account_number>12345</account_number> <balance currency="usd">100.00</balance> <link rel="deposit" href="/account/12345/deposit" /> <link rel="withdraw" href="/account/12345/withdraw" /> <link rel="transfer" href="/account/12345/transfer" /> </account>
要是你的帳戶已經赤字,你能夠作的動做就只有存款了:
GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK <?xml version="1.0"?> <account> <account_number>12345</account_number> <balance currency="usd">-25.00</balance> <link rel="deposit" href="/account/12345/deposit" /> </account>
這個動做清單是和狀態有關的,術語叫作HATEOAS (Hypertext As The Engine Of Application State) 。
咱們已經提過,」從需求文本中提取名詞和動詞」,名詞說了,就是資源的命名。動詞呢。好比對訂單的「查詢」就是動詞。
http://example.com/order/1
在REST內默認就是GET,也就是「查詢」。使用瀏覽器的場合,上面的URI在發給服務器時,會被翻譯爲
GET http://example.com/order/1
語義上來講,就是查詢在example.com上的ID爲1的訂單,使用http協議。當使用這套,在服務器放準守REST的話,你還能夠獲得額外的好處,就是:
冪等。若是你發送了一個GET請求沒有獲得結果,你可能不知道緣由是請求未能到達目的地,仍是響應在反饋的途中丟失了。冪等性保證了你能夠簡單地再發送一次請求解決問題。
緩存。因此在不少狀況下,你甚至不須要向服務器發送請求。
GET在HTTP中被叫作動詞(verb),除了GET,還有POST以外,還有PUT、DELETE、HEAD和OPTIONS。做爲OO開發者的話,就能夠想象到RESTful HTTP方案中的全部資源都繼承自相似於這樣的一個類:
class Resource { Resource(URI u); Response get(); Response post(Request r); Response put(Request r); Response delete(); }
冪等性一樣適用於:
PUT。語義爲:更新資源數據,若是資源不存在的話,則根據此URI建立一個新的資源
DELETE。語義爲:刪除一個資源,或者刪除不存在的東西沒有任何問題
POST方法,一般表示「建立一個新資源」,也能被用於調用任意過程,於是它既不安全也不具備冪等性。
爲何使用標準方法如此重要?從根本上說,它使你的應用成爲Web的一部分,統一接口也使得全部理解HTTP應用協議的組件能與你的應用交互。通用客戶程序(generic client)就是從中受益的組件的例子,例如curl、wget、代理、緩存、HTTP服務器、網關還有Google、Yahoo!、MSN等等。
REST要求狀態要麼被放入資源狀態中,要麼保存在客戶端上。或者換句話說,服務器端不能保持除了單次請求以外的,任何與其通訊的客戶端的通訊狀態。
這樣作的最直接的理由就是可伸縮性—— 若是服務器須要保持客戶端狀態,那麼大量的客戶端交互會嚴重影響服務器的內存可用空間(footprint)。
一樣一個order資源,可能響應檢索的格式是xml,爲了輕量級的支持移動app,如今須要支持json。這樣的資源表達方式變化能夠直接利用HTTP內容協商(content negotiation),而無需本身定義參數。好比原本的請求包:
GET /order/1 HTTP/1.1 Host: example.com Accept: application/vnd.mycompany.order+xml
如今可讓移動客戶端發出:
GET /order/1 HTTP/1.1 Host: example.com Accept: application/vnd.mycompany.order+json
返回的響應包內,能夠在其HTTP Content-type頭中包含着數據類型。
纔有已有標準的好處是客戶端和服務器均可以更好的達到互換:
若是客戶程序對HTTP應用協議和一組數據格式都有所「瞭解」,那麼它就能夠用一種有意義的方式與世界上任意一個RESTful HTTP應用交互。
假若從客戶端傳來的數據符合應用協議,那麼服務器端就可使用特定的格式處理數據,而不去關心客戶端的類型
原文: https://www.infoq.com/article...
改編自: http://www.infoq.com/cn/artic...
demo code : https://github.com/1000copy/s...