濟(jì)南軟件開發(fā)—為什么REST如此重要

2015-10-13 14:44:31
    本文濟(jì)南軟件開發(fā)將討論 REST,它定義了一組體系架構(gòu)原則,您可以根據(jù)這些原則設(shè)計(jì)以系統(tǒng)資源為中心的 Web 服務(wù),這是一個(gè)非常容易讓人誤解的概念。本文主要是寫給那些想設(shè)計(jì) WebService API 但卻對(duì) REST 沒有十分清晰認(rèn)識(shí)的開發(fā)者們。在本文最后會(huì)附上一些資源供大家學(xué)習(xí),這些資源講解非常詳細(xì)。
  什么是REST?
  表征狀態(tài)轉(zhuǎn)移(Representional State Transfer),是 Roy Fielding( HTTP 規(guī)范的主要編寫者之一)博士在 2000 年他的博士論文中提出來的一種軟件架構(gòu)風(fēng)格。它并不是一個(gè)標(biāo)準(zhǔn),而是通過表征(Representional )來描述傳輸狀態(tài)的一種原則。其宗旨是從資源的角度來觀察整個(gè)網(wǎng)絡(luò),分布在各處的資源由 URI 確定,而客戶端的應(yīng)用通過 URI 來獲取資源的表征。獲得這些表征致使這些應(yīng)用程序轉(zhuǎn)變了其狀態(tài)。隨著不斷獲取資源的表征,客戶端應(yīng)用不斷地在轉(zhuǎn)變著其狀態(tài)。
  目前在三種主流的 Web 服務(wù)實(shí)現(xiàn)方案中,因?yàn)?nbsp;REST 模式的 Web 服務(wù)與復(fù)雜的 SOAP 和 XML-RPC 相對(duì)比,更加簡(jiǎn)潔,越來越多的 Web 服務(wù)開始采用 REST 風(fēng)格設(shè)計(jì)和實(shí)現(xiàn)。例如,Amazon.com 提供接近 REST 風(fēng)格的 Web 服務(wù)進(jìn)行圖書查找;雅虎提供的 Web 服務(wù)也是 REST 風(fēng)格的。
  讓我們來思考一下:
  Marcus 是一個(gè)農(nóng)民,他有 4 頭牛,12 只雞和 3 頭奶牛。他現(xiàn)在模擬一個(gè) REST API,而我是客戶端。如果我想用 REST 來請(qǐng)求當(dāng)前的農(nóng)場(chǎng)狀態(tài),我僅會(huì)問:“State?”Marcus 會(huì)回答:“4 頭豬、12 只雞、3 頭奶牛”。
  這是 REST 最簡(jiǎn)單的一個(gè)例子。Marcus 使用表征來傳輸農(nóng)場(chǎng)狀態(tài)。表征的句子很簡(jiǎn)單:“4 頭豬、12 只雞、3 頭奶!。
  再往下看,看我如何讓 Marcus 用 REST 方式添加 2 頭奶牛?
  按照常理,可以會(huì)這樣說:Marcus,請(qǐng)?jiān)谵r(nóng)場(chǎng)你再添加 2 頭奶牛。難道這就是 REST 方式嗎?難道就是通過這樣的表征來傳輸狀態(tài)的嗎?不是的!這是一個(gè)遠(yuǎn)程過程調(diào)用,過程是給農(nóng)場(chǎng)添加 2 頭奶牛。
  Marcus 很憤怒地響應(yīng)到:“400,Bad Request”,你到底是什么意思?
  所以,讓我們重新來一次。我們?cè)鯓幼龅?nbsp;REST 方式呢?該怎樣重新表征呢?它應(yīng)該是 4 頭豬、12 只雞、3 頭奶牛。好,讓我們?cè)俅沃匦卤碚鳌?/span>
  我:“Marcus,……4 頭豬、12 只雞、5頭奶牛!”
  Marcus:“好的”。
  我:“Marcus,現(xiàn)在是什么狀態(tài)?”
  Marcus:“4 頭豬、12 只雞、5 頭奶牛”。
  我:“好!”
  看到了嗎?就這樣簡(jiǎn)單。
  為什么 RPC 也不夠好?
  從邏輯角度來看,為什么會(huì)更加青睞 REST 而不是 RPC(Remote Procedure Call,遠(yuǎn)程過程調(diào)用 ),因?yàn)樗鼧O大的降低了我們溝通的復(fù)雜度,通過把表征作為唯一的溝通的方式。無需去討論過程(添加一頭牛?增加一種動(dòng)物類型?給雞的數(shù)量翻倍還是賣掉所有豬?)我們只需討論表征,并且使用這個(gè)表征來達(dá)到我們想要的目標(biāo),很簡(jiǎn)單,不是嗎?我不希望和 Marcus 的溝通失敗,因?yàn)槲覀儽舜说睦斫膺^程會(huì)不一樣,所以只需要知道最后的狀態(tài)就行。但這僅僅是創(chuàng)建 RPC 會(huì)產(chǎn)生許多問題之一。如果你使用 RPC,你需要設(shè)計(jì)一些程序嵌入到某種結(jié)構(gòu)中。這種結(jié)構(gòu)需要存儲(chǔ)參數(shù)、錯(cuò)誤的代碼、返回值等。我已經(jīng)看到許多公司這樣做,他們?cè)O(shè)計(jì)自己的 RPC-結(jié)構(gòu)來實(shí)現(xiàn)客戶端與服務(wù)器端的交互,但卻產(chǎn)生許多問題。你為什么要這么做?為什么要?jiǎng)?chuàng)建自己的 RPC-結(jié)構(gòu)?這樣做的好處是?倘若我想要讓應(yīng)用程序使用許多 WebService,并且這些 WebService 帶有多個(gè) RPC-格式屬性?那么我不得不去開發(fā)一些類似這樣的東西:
  如果你們真的需要 RPC,至少要選擇一個(gè)類似 SOAP 的標(biāo)準(zhǔn)。
  但 SOAP 也很糟糕
  即使 RPC 的標(biāo)準(zhǔn)真的很令人痛苦,但我不得不承認(rèn) ACID 事務(wù),一個(gè)完整的標(biāo)準(zhǔn)化服務(wù)描述性語言 SOAP(Simple Object Access Protocol,簡(jiǎn)單對(duì)象訪問協(xié)議)在某些環(huán)境下表現(xiàn)的還不錯(cuò)。盡管如此,SOAP 產(chǎn)品的性能開銷很大,它是一個(gè)巨大的性能殺手。雖然 REST 不是一個(gè)標(biāo)準(zhǔn),但在實(shí)現(xiàn) RESTful Web 服務(wù)時(shí)可以使用其他各種標(biāo)準(zhǔn)(比如 HTTP、URL、XML、PNG 等)。
  Session 更邪惡
  你無需 Session!但有人會(huì)說:“我想要保存用戶購(gòu)物車?yán)锏纳唐,所以我必須?nbsp;Session!”不,這樣想是錯(cuò)誤的!即使沒有 Session,你也可以做你任何你想做的事情。你可以只需在 URL 里封裝購(gòu)物車信息,或者為購(gòu)物車創(chuàng)建另一個(gè)資源,比如“/carts/5235”。
  不需要與客戶端進(jìn)行會(huì)話,通過這些操作(指在 URL 里封裝購(gòu)物車信息,或者為購(gòu)物車創(chuàng)建另一個(gè)資源,比如“/carts/5235”)后,客戶端向服務(wù)器發(fā)出請(qǐng)求后,哪怕你在服務(wù)器上執(zhí)行卸載平臺(tái)和操作系統(tǒng)、拆除服務(wù)器硬件、重新組裝服務(wù)器、重新安裝操作系統(tǒng)、平臺(tái)、應(yīng)用程序備份恢復(fù)操作,也不會(huì)影響客戶端。
  不要強(qiáng)迫客戶端保存狀態(tài),這樣做不僅復(fù)雜,而且還會(huì)帶來許多問題,你應(yīng)該從你的 Web 應(yīng)用程序里刪除有狀態(tài)的東西。
  不要重造超媒體
  目前,超媒體已經(jīng)相當(dāng)普及,我提醒大家,不要再去重新造輪子。這里已經(jīng)有許多,足夠你使用了:
采用原子鏈接規(guī)范的超媒體,類似 spring-hateoas 和 spring-data-rest。