基礎(chǔ)
REST 定義了一組體系架構(gòu)原則,您可以根據(jù)這些原則設(shè)計(jì)以系統(tǒng)資源為中心的 Web 服務(wù),包括使用不同語言編寫的客戶端如何通過 HTTP 處理和傳輸資源狀態(tài)。 如果考慮使用它的 Web 服務(wù)的數(shù)量,REST 近年來已經(jīng)成為最主要的 Web 服務(wù)設(shè)計(jì)模型。 事實(shí)上,REST 對(duì) Web 的影響非常大,由于其使用相當(dāng)方便,已經(jīng)普遍地取代了基于 SOAP 和 WSDL 的接口設(shè)計(jì)。
REST 這個(gè)概念于 2000 年由 Roy Fielding 在就讀加州大學(xué)歐文分校期間在學(xué)術(shù)論文“Architectural Styles and the Design of Network-based Software Architectures”(請(qǐng)參見參考資料以獲取此論文的鏈接)首次提出,他的論文中對(duì)使用 Web 服務(wù)作為分布式計(jì)算平臺(tái)的一系列軟件體系結(jié)構(gòu)原則進(jìn)行了分析,而其中提出的 REST 概念并沒有獲得現(xiàn)在這么多關(guān)注。 多年以后的今天,REST 的主要框架已經(jīng)開始出現(xiàn),但仍然在開發(fā)中,因?yàn)樗呀?jīng)被廣泛接納到各個(gè)平臺(tái)中,例如通過 JSR-311 成為了 Java™ 6 不可或缺的部分。
本文認(rèn)為,對(duì)于今天正在吸引如此多注意力的最純粹形式的 REST Web 服務(wù),其具體實(shí)現(xiàn)應(yīng)該遵循四個(gè)基本設(shè)計(jì)原則:
- 顯式地使用 HTTP 方法。
- 無狀態(tài)。
- 公開目錄結(jié)構(gòu)式的 URI。
- 傳輸 XML、JavaScript Object Notation (JSON),或同時(shí)傳輸這兩者。
下面幾個(gè)部分將詳述這四個(gè)原則,并提供技術(shù)原理解釋,說明為什么這些原則對(duì) REST Web 服務(wù)設(shè)計(jì)人員非常重要。
顯式地使用 HTTP 方法
基于 REST 的 Web 服務(wù)的主要特征之一是以遵循 RFC 2616 定義的協(xié)議的方式顯式使用 HTTP 方法。例如,HTTP GET 被定義為數(shù)據(jù)產(chǎn)生方法,旨在由客戶端應(yīng)用程序用于檢索資源以從 Web 服務(wù)器獲取數(shù)據(jù),或者執(zhí)行某個(gè)查詢并預(yù)期 Web 服務(wù)器將查找某一組匹配資源然后使用該資源進(jìn)行響應(yīng)。
REST 要求開發(fā)人員顯式地使用 HTTP 方法,并且使用方式與協(xié)議定義一致。 這個(gè)基本 REST 設(shè)計(jì)原則建立了創(chuàng)建、讀取、更新和刪除(create, read, update, and delete,CRUD)操作與 HTTP 方法之間的一對(duì)一映射。 根據(jù)此映射:
- 若要在服務(wù)器上創(chuàng)建資源,應(yīng)該使用 POST 方法。
- 若要檢索某個(gè)資源,應(yīng)該使用 GET 方法。
- 若要更改資源狀態(tài)或?qū)ζ溥M(jìn)行更新,應(yīng)該使用 PUT 方法。
- 若要?jiǎng)h除某個(gè)資源,應(yīng)該使用 DELETE 方法。
許多 Web API 中所固有的一個(gè)令人遺憾的設(shè)計(jì)缺陷在于將 HTTP 方法用于非預(yù)期用途。 例如,HTTP GET 請(qǐng)求中的請(qǐng)求 URI 通常標(biāo)識(shí)一個(gè)特定的資源。 或者,請(qǐng)求 URI 中的查詢字符串包括一組參數(shù),這些參數(shù)定義服務(wù)器用于查找一組匹配資源的搜索條件。 至少,HTTP/1.1 RFC 是這樣描述 GET 方法的。 但是在許多情況下,不優(yōu)雅的 Web API 使用 HTTP GET 來觸發(fā)服務(wù)器上的事務(wù)性操作——例如,向數(shù)據(jù)庫添加記錄。 在這些情況下,GET 請(qǐng)求 URI 屬于不正確使用,或者至少不是以基于 REST 的方式使用。 如果 Web API 使用 GET 調(diào)用遠(yuǎn)程過程,則應(yīng)該類似如下:
GET /adduser?name=Robert HTTP/1.1
這不是非常優(yōu)雅的設(shè)計(jì),因?yàn)樯厦娴?Web 方法支持通過 HTTP GET 進(jìn)行狀態(tài)更改操作。 換句話說,該 HTTP GET 請(qǐng)求具有副作用。 如果處理成功,則該請(qǐng)求的結(jié)果是向基礎(chǔ)數(shù)據(jù)存儲(chǔ)區(qū)添加一個(gè)新用戶——在此例中為 Robert。 這里的問題主要在語義上。 Web 服務(wù)器旨在通過檢索與請(qǐng)求 URI 中的路徑(或查詢條件)匹配的資源,并在響應(yīng)中返回這些資源或其表示形式,從而響應(yīng) HTTP GET 請(qǐng)求,而不是向數(shù)據(jù)庫添加記錄。 從該協(xié)議方法的預(yù)期用途的角度看,然后再從與 HTTP/1.1 兼容的 Web 服務(wù)器的角度看,以這種方式使用 GET 是不一致的。
除了語義之外,GET 的其他問題在于,為了觸發(fā)數(shù)據(jù)庫中的記錄的刪除、修改或添加,或者以某種方式更改服務(wù)器端狀態(tài),它請(qǐng)求 Web 緩存工具(爬網(wǎng)程序)和搜索引擎簡單地通過對(duì)某個(gè)鏈接進(jìn)行爬網(wǎng)處理,從而意外地做出服務(wù)器端更改。 克服此常見問題的簡單方法是將請(qǐng)求 URI 上的參數(shù)名稱和值轉(zhuǎn)移到 XML 標(biāo)記中。 這樣產(chǎn)生的標(biāo)記是要?jiǎng)?chuàng)建的實(shí)體的 XML 表示形式,可以在 HTTP POST 的正文中進(jìn)行發(fā)送,此 HTTP POST 的請(qǐng)求 URI 是該實(shí)體的預(yù)期父實(shí)體(請(qǐng)參見清單 1 和 2):
清單 1. 之前
GET /adduser?name=Robert HTTP/1.1
|
清單 2. 之后
POST /users HTTP/1.1
Host: myserver
Content-Type: application/xml
<?xml version="1.0"?>
<user>
<name>Robert</name>
</user>
|
上述方法是基于 REST 的請(qǐng)求的范例: 正確使用 HTTP POST 并將有效負(fù)載包括在請(qǐng)求的正文中。 在接收端,可以通過將正文中包含的資源添加為請(qǐng)求 URI 中標(biāo)識(shí)的資源的從屬資源,從而處理該請(qǐng)求;在此例下,應(yīng)該將新資源添加為 /users
的子項(xiàng)。 POST 請(qǐng)求中指定的這種新實(shí)體與其父實(shí)體之間的包含關(guān)系類似于某個(gè)文件從屬于其父目錄的方式。 客戶端設(shè)置實(shí)體與其父實(shí)體之間的關(guān)系,并在 POST 請(qǐng)求中定義新實(shí)體的 URI。
然后客戶端應(yīng)用程序可以使用新的 URI 獲取資源的表示形式,并至少邏輯地指明該資源位于 /users
之下,如清單 3 所示。
清單 3. HTTP GET 請(qǐng)求
GET /users/Robert HTTP/1.1
Host: myserver
Accept: application/xml
|
以這種方式使用 GET 是顯式的,因?yàn)?GET 僅用于數(shù)據(jù)檢索。 GET 是應(yīng)該沒有副作用的操作,即所謂的等冪性 屬性。
當(dāng)支持通過 HTTP GET 執(zhí)行更新操作時(shí),也需要應(yīng)用類似的 Web 方法重構(gòu),如清單 4 所示。
清單 4. 通過 HTTP GET 進(jìn)行更新
GET /updateuser?name=Robert&newname=Bob HTTP/1.1
|
這更改了資源的 name
特性(或?qū)傩裕?雖然可以將查詢字符串用于此類操作,清單 4 就是一個(gè)簡單的例子,但是在用于較復(fù)雜的操作時(shí),這種將查詢字符串作為方法簽名的模式往往會(huì)崩潰。 由于您的目標(biāo)是顯式使用 HTTP 方法,鑒于上述的相同原因(請(qǐng)參見清單 5),更符合 REST 的方法是發(fā)送 HTTP PUT 請(qǐng)求以更新資源,而不是發(fā)送 HTTP GET。
清單 5. HTTP PUT 請(qǐng)求
PUT /users/Robert HTTP/1.1
Host: myserver
Content-Type: application/xml
<?xml version="1.0"?>
<user>
<name>Bob</name>
</user>
|
使用 PUT 取代原始資源可以提供更清潔的接口,這樣的接口與 REST 的原則以及與 HTTP 方法的定義一致。 清單 5 中的 PUT 請(qǐng)求是顯式的,因?yàn)樗ㄟ^在請(qǐng)求 URI 中標(biāo)識(shí)要更新的資源來指向該資源,并且它在 PUT 請(qǐng)求的正文中將資源的新表示形式從客戶端傳輸?shù)椒?wù)器,而不是在請(qǐng)求 URI 上將資源屬性作為參數(shù)名稱和值的松散集合進(jìn)行傳輸。 清單 5 還具有將資源從 Robert
重命名為 Bob
的效果,這樣做會(huì)將其 URI 更改為 /users/Bob
。 在 REST Web 服務(wù)中,使用舊的 URI 針對(duì)該資源的后續(xù)請(qǐng)求會(huì)產(chǎn)生標(biāo)準(zhǔn)的 404 Not Found 錯(cuò)誤。
作為一般設(shè)計(jì)原則,通過在 URI 中使用名詞而不是動(dòng)詞,對(duì)于遵循有關(guān)顯式使用 HTTP 方法的 REST 指導(dǎo)原則是有幫助的。 在基于 REST 的 Web 服務(wù)中,協(xié)議已經(jīng)對(duì)動(dòng)詞(POST、GET、PUT 和 DELETE)進(jìn)行了定義。 在理想的情況下,為了保持接口的通用化,并允許客戶端明確它們調(diào)用的操作,Web 服務(wù)不應(yīng)該定義更多的動(dòng)詞或遠(yuǎn)程過程,例如 /adduser
或 /updateuser
。 這條通用設(shè)計(jì)原則也適用于 HTTP 請(qǐng)求的正文,后者旨在用于傳輸資源狀態(tài),而不是用于攜帶要調(diào)用的遠(yuǎn)程方法或遠(yuǎn)程過程的名稱。
無狀態(tài)
REST Web 服務(wù)需要擴(kuò)展以滿足日益提高的性能要求。 具有負(fù)載平衡和故障轉(zhuǎn)移功能、代理和網(wǎng)關(guān)的服務(wù)器集群通常以形成服務(wù)拓?fù)涞姆绞竭M(jìn)行組織,從而允許根據(jù)需要將請(qǐng)求從一個(gè)服務(wù)器路由到另一個(gè)服務(wù)器,以減少 Web 服務(wù)調(diào)用的總體響應(yīng)時(shí)間。 要使用中間服務(wù)器擴(kuò)大規(guī)模,REST Web 服務(wù)需要發(fā)送完整、獨(dú)立的請(qǐng)求;也就是說,發(fā)送的請(qǐng)求包括所有需要滿足的數(shù)據(jù),以便中間服務(wù)器中的組件能夠進(jìn)行轉(zhuǎn)發(fā)、路由和負(fù)載平衡,而不需要在請(qǐng)求之間在本地保存任何狀態(tài)。
完整、獨(dú)立的請(qǐng)求不要求服務(wù)器在處理請(qǐng)求時(shí)檢索任何類型的應(yīng)用程序上下文或狀態(tài)。 REST Web 服務(wù)應(yīng)用程序(或客戶端)在 HTTP Header 和請(qǐng)求正文中包括服務(wù)器端組件生成響應(yīng)所需要的所有參數(shù)、上下文和數(shù)據(jù)。 這種意義上的無狀態(tài)可以改進(jìn) Web 服務(wù)性能,并簡化服務(wù)器端組件的設(shè)計(jì)和實(shí)現(xiàn),因?yàn)榉?wù)器上沒有狀態(tài),從而消除了與外部應(yīng)用程序同步會(huì)話數(shù)據(jù)的需要。
圖 1 演示了一個(gè)有狀態(tài)的服務(wù),某個(gè)應(yīng)用程序可能向其請(qǐng)求多頁結(jié)果集中的下一個(gè)頁面,并假設(shè)該服務(wù)跟蹤應(yīng)用程序在結(jié)果集中導(dǎo)航時(shí)的離開位置。 在這個(gè)有狀態(tài)的設(shè)計(jì)中,該服務(wù)遞增并在某個(gè)位置存儲(chǔ) previousPage
變量,以便能夠響應(yīng)針對(duì)下一個(gè)頁面的請(qǐng)求。
圖 1. 有狀態(tài)的設(shè)計(jì)
類似如此的有狀態(tài)的服務(wù)變得復(fù)雜化了。 在 Java Platform, Enterprise Edition (Java EE) 環(huán)境中,有狀態(tài)的服務(wù)需要大量的預(yù)先考慮,以高效地存儲(chǔ)會(huì)話數(shù)據(jù)和支持整個(gè) Java EE 容器集群中的會(huì)話數(shù)據(jù)同步。 在此類環(huán)境中,存在一個(gè) Servlet/JavaServer Pages (JSP) 和 Enterprise JavaBeans (EJB) 開發(fā)人員非常熟悉的問題,他們經(jīng)常在會(huì)話復(fù)制過程中艱難地查找引發(fā) java.io.NotSerializableException
的根源。 無論該異常是由 Servlet 容器在 HttpSession
復(fù)制過程中引發(fā)的,還是由 EJB 容器在有狀態(tài)的 EJB 復(fù)制過程中引發(fā)的,這都是個(gè)問題,會(huì)耗費(fèi)開發(fā)人員幾天的時(shí)間,嘗試在構(gòu)成服務(wù)器狀態(tài)并且有時(shí)非常復(fù)雜的對(duì)象圖表中查明沒有實(shí)現(xiàn) Serializable
的對(duì)象。 此外,會(huì)話同步增加了開銷,從而影響服務(wù)器性能。
另一方面,無狀態(tài)的服務(wù)器端組件不那么復(fù)雜,很容易跨進(jìn)行負(fù)載平衡的服務(wù)器進(jìn)行設(shè)計(jì)、編寫和分布。 無狀態(tài)的服務(wù)不僅性能更好,而且還將大部分狀態(tài)維護(hù)職責(zé)轉(zhuǎn)移給客戶端應(yīng)用程序。 在基于 REST 的 Web 服務(wù)中,服務(wù)器負(fù)責(zé)生成響應(yīng),并提供使客戶端能夠獨(dú)自維護(hù)應(yīng)用程序狀態(tài)的接口。 例如,在針對(duì)多頁結(jié)果集的請(qǐng)求中,客戶端應(yīng)該包括要檢索的實(shí)際頁編號(hào),而不是簡單地要求檢索下一頁(請(qǐng)參見圖 2)。
圖 2. 無狀態(tài)的設(shè)計(jì)
無狀態(tài)的 Web 服務(wù)生成的響應(yīng)鏈接到結(jié)果集中的下一個(gè)頁編號(hào),并允許客戶端完成所需的相關(guān)工作以便保留此值。 可以作為大致的分離將基于 REST 的 Web 服務(wù)設(shè)計(jì)的這個(gè)方面劃分為兩組職責(zé),以闡明如何維護(hù)無狀態(tài)的服務(wù):
服務(wù)器
- 生成響應(yīng),其中包括指向其他資源的鏈接,以使得應(yīng)用程序可以在相關(guān)資源之間導(dǎo)航。 此類響應(yīng)嵌入了鏈接。 類似地,如果請(qǐng)求是針對(duì)父或容器資源,則基于 REST 的典型響應(yīng)還可能包括指向父資源的子資源或從屬資源的鏈接,以便這些資源保持連接在一起。
- 生成響應(yīng),其中指明了是否可緩存,以通過減少針對(duì)重復(fù)資源的請(qǐng)求數(shù)量或通過完全消除某些請(qǐng)求來改進(jìn)性能。 服務(wù)器通過包括 Cache-Control 和 Last-Modified(日期值)HTTP 響應(yīng) Header 實(shí)現(xiàn)此目的。
客戶端應(yīng)用程序
- 使用 Cache-Control 響應(yīng) Header 確定是否緩存資源(創(chuàng)建資源的本地副本)。 客戶端還讀取 Last-Modified 響應(yīng) Header,并在 If-Modified-Since Header 中發(fā)回日期值,以向服務(wù)器詢問資源是否已更改。 這稱為條件 GET (Conditional GET),兩個(gè) Header 同時(shí)進(jìn)行,因?yàn)榉?wù)器的響應(yīng)為標(biāo)準(zhǔn) 304 代碼 (Not Modified),如果請(qǐng)求的資源自從該時(shí)間以后尚未更改,則省略實(shí)際的資源。 HTTP 響應(yīng)代碼 304 意味著客戶端可以安全地將資源表示形式的緩存本地副本作為最新版本使用,從而實(shí)際上跳過了后續(xù) GET 請(qǐng)求,直到資源更改為止。
- 發(fā)送可獨(dú)立于其他請(qǐng)求得到服務(wù)的完整請(qǐng)求。 這要求客戶端充分利用 Web 服務(wù)接口指定的 HTTP Header,并在請(qǐng)求正文中發(fā)送完整的資源表示形式。 客戶端發(fā)送的請(qǐng)求極少對(duì)先前的請(qǐng)求、某個(gè)會(huì)話在服務(wù)器上的存在性、服務(wù)器向請(qǐng)求添加上下文的能力或請(qǐng)求之間保留的應(yīng)用程序狀態(tài)做出假設(shè)。
客戶端應(yīng)用程序與服務(wù)之間的這種協(xié)作對(duì)于基于 REST 的 Web 服務(wù)中的無狀態(tài)性極為重要。 它通過節(jié)省帶寬和最小化服務(wù)器端應(yīng)用程序狀態(tài)改進(jìn)了性能。
公開目錄結(jié)構(gòu)式的 URI
從對(duì)資源尋址的客戶端應(yīng)用程序的角度看,URI 決定了 REST Web 服務(wù)將具有的直觀程度,以及服務(wù)是否將以設(shè)計(jì)人員能夠預(yù)測(cè)的方式被使用。 基于 REST 的 Web 服務(wù)的第三個(gè)特征完全與 URI 相關(guān)。
REST Web 服務(wù) URI 的直觀性應(yīng)該達(dá)到很容易猜測(cè)的程度。 將 URI 看作是自身配備文檔說明的接口,開發(fā)人員只需很少(如果有的話)的解釋或參考資料即可了解它指向什么,并獲得相關(guān)的資源。 為此,URI 的結(jié)構(gòu)應(yīng)該簡單、可預(yù)測(cè)且易于理解。
實(shí)現(xiàn)這種級(jí)別的可用性的方法之一是定義目錄結(jié)構(gòu)式的 URI。 此類 URI 具有層次結(jié)構(gòu),其根為單個(gè)路徑,從根開始分支的是公開服務(wù)的主要方面的子路徑。 根據(jù)此定義,URI 并不只是斜杠分隔的字符串,而是具有在節(jié)點(diǎn)上連接在一起的下級(jí)和上級(jí)分支的樹。 例如,在一個(gè)收集從 Java 到報(bào)紙的各種主題的討論線程服務(wù)中,您可能定義類似如下的結(jié)構(gòu)化 URI 集合:
http://www.myservice.org/discussion/topics/{topic}
根 /discussion
之下有一個(gè) /topics
節(jié)點(diǎn)。 該節(jié)點(diǎn)之下有一系列主題名稱,例如閑談、技術(shù)等等,每個(gè)主題名稱指向某個(gè)討論線程。 在此結(jié)構(gòu)中,只需在 /topics/ 后面輸入某個(gè)內(nèi)容即可容易地收集討論線程。
在某些情況下,指向資源的路徑尤其適合于目錄式結(jié)構(gòu)。 例如,以按日期進(jìn)行組織的資源為例,這種資源非常適合于使用層次結(jié)構(gòu)語法。
此示例非常直觀,因?yàn)樗谝?guī)則:
http://www.myservice.org/discussion/2008/12/10/{topic}
第一個(gè)路徑片段是四個(gè)數(shù)字的年份,第二個(gè)路徑片斷是兩個(gè)數(shù)字的日期,第三個(gè)片段是兩個(gè)數(shù)字的月份。 這樣解釋它可能有點(diǎn)愚蠢,但這就是我們追求的簡單級(jí)別。 人類和計(jì)算機(jī)能夠容易地生成類似如此的結(jié)構(gòu)化 URI,因?yàn)檫@些 URI 基于規(guī)則。 在語法的空隙中填入路徑部分就大功告成了,因?yàn)榇嬖谟糜诮M合 URI 的明確模式:
http://www.myservice.org/discussion/{year}/{day}/{month}/{topic}
在考慮基于 REST 的 Web 服務(wù)的 URI 結(jié)構(gòu)時(shí),需要指出的一些附加指導(dǎo)原則包括:
- 隱藏服務(wù)器端腳本技術(shù)文件擴(kuò)展名(.jsp、.php、.asp)——如果有的話,以便您能夠移植到其他腳本技術(shù)而不用更改 URI。
- 將所有內(nèi)容保持小寫。
- 將空格替換為連字符或下劃線(其中一種或另一種)。
- 盡可能多地避免查詢字符串。
- 如果請(qǐng)求 URI 用于部分路徑,與使用 404 Not Found 代碼不同,應(yīng)該始終提供缺省頁面或資源作為響應(yīng)。
URI 還應(yīng)該是靜態(tài)的,以便在資源發(fā)生更改或服務(wù)的實(shí)現(xiàn)發(fā)生更改時(shí),鏈接保持不變。 這可以實(shí)現(xiàn)書簽功能。 URI 中編碼的資源之間的關(guān)系與在存儲(chǔ)資源的位置表示資源關(guān)系的方式無關(guān)也是非常重要的。
傳輸 XML、JSON 或同時(shí)傳輸這兩者
資源表示形式通常反映了在客戶端應(yīng)用程序請(qǐng)求資源時(shí)的資源當(dāng)前狀態(tài)及其屬性。 這種意義上的資源表示形式只是時(shí)間上的快照。 這可以像數(shù)據(jù)庫中的記錄表示形式一樣簡單,其中包括列名稱與 XML 標(biāo)記之間的映射,XML 中的元素值包含行值。 或者,如果系統(tǒng)具有數(shù)據(jù)模型,那么根據(jù)此定義,資源表示形式是系統(tǒng)的數(shù)據(jù)模型中的對(duì)象之一的屬性快照。 這些對(duì)象就是您希望您的 REST Web 服務(wù)為客戶端提供的資源。
基于 REST 的 Web 服務(wù)設(shè)計(jì)中的最后一組約束與應(yīng)用程序和服務(wù)在請(qǐng)求/響應(yīng)有效負(fù)載或 HTTP 正文中交換的數(shù)據(jù)的格式有關(guān)。 這是真正值得將一切保持簡單、可讀和連接在一起的方面。
數(shù)據(jù)模型中的對(duì)象通常以某種方式相關(guān),應(yīng)該以在將資源傳輸?shù)娇蛻舳藨?yīng)用程序時(shí)表示資源的方式,反映數(shù)據(jù)模型對(duì)象(資源)之間的關(guān)系。 在討論線程服務(wù)中,連接的資源表示形式的示例可能包括根討論主題及其屬性,以及指向?yàn)樵撝黝}提供的響應(yīng)的嵌入鏈接。
清單 6. 討論線程的 XML 表示形式
<?xml version="1.0"?>
<discussion date="{date}" topic="{topic}">
<comment>{comment}</comment>
<replies>
<reply from="joe@mail.com" href="/discussion/topics/{topic}/joe"/>
<reply from="bob@mail.com" href="/discussion/topics/{topic}/bob"/>
</replies>
</discussion>
|
最后,為了賦予客戶端請(qǐng)求最適合它們的特定內(nèi)容類型的能力,您的服務(wù)的構(gòu)造應(yīng)該利用內(nèi)置的 HTTP Accept Header,其中該 Header 的值為 MIME 類型。 基于 REST 的服務(wù)使用的一些常見 MIME 類型如表 1 所示。
表 1. 基于 REST 的服務(wù)使用的常見 MIME 類型
MIME-Type |
Content-Type |
JSON |
application/json |
XML |
application/xml |
XHTML |
application/xhtml+xml |
這使得服務(wù)可由運(yùn)行在不同平臺(tái)和設(shè)備上并采用不同語言編寫的各種各樣的客戶端所使用。 使用 MIME 類型和 HTTP Accept Header 是一種稱為內(nèi)容協(xié)商 的機(jī)制,這種機(jī)制允許客戶端選擇適合于它們的數(shù)據(jù)格式,并最小化服務(wù)與使用服務(wù)的應(yīng)用程序之間的數(shù)據(jù)耦合。
回頁首
結(jié)束語
REST 并非始終是正確的選擇。 它作為一種設(shè)計(jì) Web 服務(wù)的方法而變得流行,這種方法對(duì)專有中間件(例如某個(gè)應(yīng)用程序服務(wù)器)的依賴比基于 SOAP 和 WSDL 的方法更少。 在某種意義上,通過強(qiáng)調(diào) URI 和 HTTP 等早期 Internet 標(biāo)準(zhǔn),REST 是對(duì)大型應(yīng)用程序服務(wù)器時(shí)代之前的 Web 方式的回歸。 正如您已經(jīng)在所謂的基于 REST 的接口設(shè)計(jì)原則中研究過的一樣,XML over HTTP 是一個(gè)功能強(qiáng)大的接口,允許內(nèi)部應(yīng)用程序(例如基于 Asynchronous JavaScript + XML (Ajax) 的自定義用戶界面)輕松連接、定位和使用資源。 事實(shí)上,Ajax 與 REST 之間的完美配合已增加了當(dāng)今人們對(duì) REST 的注意力。
通過基于 REST 的 API 公開系統(tǒng)資源是一種靈活的方法,可以為不同種類的應(yīng)用程序提供以標(biāo)準(zhǔn)方式格式化的數(shù)據(jù)。 它可以幫助滿足集成需求(這對(duì)于構(gòu)建可在其中容易地組合 (Mashup) 數(shù)據(jù)的系統(tǒng)非常關(guān)鍵),并幫助將基于 REST 的基本服務(wù)集擴(kuò)展或構(gòu)建為更大的集合。 本文僅略微談到了基礎(chǔ),但愿本文的討論會(huì)誘發(fā)您繼續(xù)探索該主題。
參考資料
學(xué)習(xí)
獲得產(chǎn)品和技術(shù)
討論
原文地址:http://www.ibm.com/developerworks/cn/webservices/ws-restful/