SOAP
什麼是SOAP,我想不用多說,google一把滿眼都是。其實SOAP最先是針對RPC的一種解決方案,簡單對象訪問協議,很輕量,同時做爲應用協議能夠基於多種傳輸協議來傳遞消息(Http,SMTP等)。可是隨着SOAP做爲WebService的普遍應用,不斷地增長附加的內容,使得如今開發人員以爲SOAP很重,使用門檻很高。在SOAP後續的發展過程當中,WS-*一系列協議的制定,增長了SOAP的成熟度,也給SOAP增長了負擔。
REST
REST其實並非什麼協議也不是什麼標準,而是將Http協議的設計初衷做了詮釋,在Http協議被普遍利用的今天,愈來愈多的是將其做爲傳輸協議,而非原先設計者所考慮的應用協議。SOAP類型的WebService就是最好的例子,SOAP消息徹底就是將Http協議做爲消息承載,以致於對於Http協議中的各類參數(例如編碼,錯誤碼等)都置之不顧。其實,最輕量級的應用協議就是Http協議。Http協議所抽象的get,post,put,delete就比如數據庫中最基本的增刪改查,而互聯網上的各類資源就比如數據庫中的記錄,對於各類資源的操做最後老是能抽象成爲這四種基本操做,在定義了定位資源的規則之後,對於資源的操做經過標準的Http協議就能夠實現,開發者也會受益於這種輕量級的協議。java
REST專門針對網絡應用設計和開發方式,以下降開發的複雜性,提升系統的可伸縮性。REST提出設計概念和準則爲:
1. 網絡上的全部事物均可以被抽象爲資源(resource)
2. 每個資源都有惟一的資源標識(resource identifier),對資源的操做不會改變這些標識
3. 全部的操做都是無狀態的
REST簡化開發,其架構遵循CRUD原則,該原則告訴咱們對於資源(包括網絡資源)只須要四種行爲:建立,獲取,更新和刪除就能夠完成相關的操做和處理。咱們能夠經過統一資源標識符(Universal Resource Identifier,URI)來識別和定位資源,而且針對這些資源而執行的操做是經過 HTTP 規範定義的。其核心操做只有GET,PUT,POST,DELETE。因爲REST強制全部的操做都必須是stateless的,這就沒有上下文的約束,若是作分佈式,集羣都不須要考慮上下文和會話保持的問題。極大的提升系統的可伸縮性。web
SOAP webService有嚴格的規範和標準,包括安全,事務等各個方面的內容,同時SOAP強調操做方法和操做對象的分離,有WSDL文件規範和XSD文件分別對其定義。數據庫
若是從這個意義上講,是否使用REST就須要考慮資源自己的抽象和識別是否困難,若是自己就是簡單的相似增刪改查的業務操做,那麼抽象資源就比較容易,而對於複雜的業務活動抽象資源並非一個簡單的事情。好比校驗用戶等級,轉帳,事務處理等,這些每每並不容易簡單的抽象爲資源。
其次若是有嚴格的規範和標準定義要求,並且前期規範標準須要指導多個業務系統集成和開發的時候,SOAP風格因爲有清晰的規範標準定義是明顯有優點的。咱們能夠在開始和實現以前就嚴格定義相關的接口方法和接口傳輸數據。(不少狀況下是爲了兼容之前項目且前臺調用邏輯代碼都不能動的前提下,更改底層應用,通常就須要使用webService模式開發,由於老代碼中已經有了明確的方法定義以及參數類型、個數等申明)
簡單數據操做,無事務處理,開發和調用簡單這些是使用REST架構風格的優點。而對於較爲複雜的面向活動的服務,若是咱們仍是使用REST,不少時候都是仍然是傳統的面向活動的思想經過轉換工具再轉換獲得REST服務,這種使用方式是沒有意義的。瀏覽器
簡單對象訪問協議(Simple Object Access Protocol,SOAP)是一種基於 XML 的協議,能夠和現存的許多因特網協議和格式結合使用,包括超文本傳輸協議(HTTP),簡單郵件傳輸協議(SMTP),多用途網際郵件擴充協議(MIME),基於「通用」傳輸協議是 SOAP的一個優勢。它還支持從消息系統到遠程過程調用(Remote Procedure Call,RPC)等大量的應用程序。SOAP提供了一系列的標準,如WSRM(WS-Reliable Messaging)形式化契約確保可靠性與安全性,確保異步處理與調用;WS-Security、WS-Transactions和WS-Coordination等標準提供了上下文信息與對話狀態管理。緩存
相對而言,SOAP協議屬於複雜的、重量級的協議,當前隨着Web2.0的興起,表述性狀態轉移(Representational State Transfer,REST)逐步成爲一個流行的架構風格。REST是一種輕量級的Web Service架構風格,其實現和操做比SOAP和XML-RPC更爲簡潔,能夠徹底經過HTTP協議實現,還能夠利用緩存Cache來提升響應速度,性能、效率和易用性上都優於SOAP協議。REST架構對資源的操做包括獲取、建立、修改和刪除資源的操做正好對應HTTP協議提供的GET、POST、PUT和DELETE方法,這種針對網絡應用的設計和開發方式,能夠下降開發的複雜性,提升系統的可伸縮性。REST架構尤爲適用於徹底無狀態的CRUD(Create、Read、Update、Delete,建立、讀取、更新、刪除)操做。安全
基於REST的軟件體系結構風格(Software Architecture Style)稱之爲面向資源體系架構(Resource-oriented Architecture,ROA)。按照REST原則設計的軟件、體系結構,一般被稱爲「REST式的」(RESTful),在本文中如下稱之爲RESTful Web服務,以便於和基於SOAP的Web服務區別。服務器
服務器端採用J2EE,客戶端採用JSP、Flex、JavaFX、AIR等能夠直接調用Servlet,其餘的實現技術基本上不能直接調用,可是不管是那種客戶端,對於基於SOAP的Web服務或者基於RESTful Web服務務都是支持的,如AJAX的 XMLHttpRequest、Flex的HTTPService等。以下圖所示:網絡
HTTP 的 GET、HEAD 請求本質上應該是安全的調用,即:GET、HEAD 調用不會有任何的反作用,不會形成服務器端狀態的改變。對於服務器來講,客戶端對某一 URI 作 n 次的 GET、HAED 調用,其狀態與沒有作調用是同樣的,不會發生任何的改變。架構
HTTP 的 PUT、DELTE 調用,具備冪指相等特性 , 即:客戶端對某一 URI 作 n 次的 PUT、DELTE 調用,其效果與作一次的調用是同樣的。HTTP 的 GET、HEAD 方法也具備冪指相等特性。less
HTTP 這些標準方法在原則上保證你的分佈式系統具備這些特性,以幫助構建更加健壯的分佈式系統。
爲了說明問題,基於上面的在線用戶管理系統,咱們給定如下場景:
參考一開始咱們給出的用例圖,對於客戶端 Client2,咱們只但願它能以只讀的方式訪問 User 和 User List 資源,而 Client1 具備訪問全部資源的全部權限。
如何作這樣的安全控制?
通行的作法是:全部從客戶端 Client2 發出的 HTTP 請求都通過代理服務器 (Proxy Server)。代理服務器制定安全策略:全部通過該代理的訪問 User 和 User List 資源的請求只具備讀取權限,即:容許 GET/HEAD 操做,而像具備寫權限的 PUT/DELTE 是不被容許的。
若是對於 REST,咱們看看這樣的安全策略是如何部署的。以下圖所示:
通常代理服務器的實現根據 (URI, HTTP Method) 兩元組來決定 HTTP 請求的安全合法性。
當發現相似於(http://localhost:8182/v1/users/{username},DELETE)這樣的請求時,予以拒絕。
對於 SOAP,若是咱們想借助於既有的代理服務器進行安全控制,會比較尷尬,以下圖:
全部的 SOAP 消息通過代理服務器,只能看到(http://localhost:8182/v1/soap/servlet/messagerouter, HTTP POST)這樣的信息,若是代理服務器想知道當前的 HTTP 請求具體作的是什麼,必須對 SOAP 的消息體解碼,這樣的話,意味着要求第三方的代理服務器須要理解當前的 SOAP 消息語義,而這種 SOAP 應用與代理服務器之間的緊耦合關係是不合理的。
衆所周知,對於基於網絡的分佈式應用,網絡傳輸是一個影響應用性能的重要因素。如何使用緩存來節省網絡傳輸帶來的開銷,這是每個構建分佈式網絡應用的開發人員必須考慮的問題。
HTTP 協議帶條件的 HTTP GET 請求 (Conditional GET) 被設計用來節省客戶端與服務器之間網絡傳輸帶來的開銷,這也給客戶端實現 Cache 機制 ( 包括在客戶端與服務器之間的任何代理 ) 提供了可能。HTTP 協議經過 HTTP HEADER 域:If-Modified-Since/Last- Modified,If-None-Match/ETag 實現帶條件的 GET 請求。
REST 的應用能夠充分地挖掘 HTTP 協議對緩存支持的能力。當客戶端第一次發送 HTTP GET 請求給服務器得到內容後,該內容可能被緩存服務器 (Cache Server) 緩存。當下一次客戶端請求一樣的資源時,緩存能夠直接給出響應,而不須要請求遠程的服務器得到。而這一切對客戶端來講都是透明的。
而對於 SOAP,狀況又是怎樣的呢?
使用 HTTP 協議的 SOAP,因爲其設計原則上並不像 REST 那樣強調與 Web 的工做方式相一致,因此,基於 SOAP 應用很難充分發揮 HTTP 自己的緩存能力。
兩個因素決定了基於 SOAP 應用的緩存機制要遠比 REST 複雜:
其一、全部通過緩存服務器的 SOAP 消息老是 HTTP POST,緩存服務器若是不解碼 SOAP 消息體,無法知道該 HTTP 請求是不是想從服務器得到數據。
其二、SOAP 消息所使用的 URI 老是指向 SOAP 的服務器,如本文例子中的
http://localhost:8182/v1/soap/servlet/messagerouter
,這並無表達真實的資源 URI,其結果是緩存服務器根本不知道那個資源正在被請求,更不用談進行緩存處理。
在一個純的 SOAP 應用中,URI 本質上除了用來指示 SOAP 服務器外,自己沒有任何意義。與 REST 的不一樣的是,沒法經過 URI 驅動 SOAP 方法調用。例如在咱們的例子中,當咱們經過
getUserList SOAP 消息得到全部的用戶列表後,仍然沒法經過既有的信息獲得某個具體的用戶信息。惟一的方法只有經過 WSDL 的指示,經過調用 getUserByName 得到,getUserList 與 getUserByName 是彼此孤立的。
而對於 REST,狀況是徹底不一樣的:經過
1
|
http:
//localhost:8182/v1/users
|
URI 得到用戶列表,而後再經過用戶列表中所提供的 LINK 屬性,例如
1
|
<link>http:
//localhost:8182/v1/users/tester</link>
|
得到 tester 用戶的用戶信息。這樣的工做方式,很是相似於你在瀏覽器的某個頁面上點擊某個 hyperlink, 瀏覽器幫你自動定向到你想訪問的頁面,並不依賴任何第三方的信息
REST 構建的系統其系統的擴展能力要強於 SOAP,這能夠體如今它的統一接口抽象、代理服務器支持、緩存服務器支持等諸多方面, 而SOAP的成熟性能夠給須要提供給多開發語言的,多傳輸方式的,對於安全性要求較高的接口設計帶來便利。
關於鏈接性 在一個純的 SOAP 應用中,URI 本質上除了用來指示 SOAP 服務器外,自己沒有任何意義。與 REST 的不一樣的是,沒法經過 URI 驅動 SOAP 方法調用。例如在咱們的例子中,當咱們經過 getUserList SOAP 消息得到全部的用戶列表後,仍然沒法經過既有的信息獲得某個具體的用戶信息。惟一的方法只有經過 WSDL 的指示,經過調用 getUserByName 得到,getUserList 與 getUserByName 是彼此孤立的。 而對於 REST,狀況是徹底不一樣的:經過 http://localhost:8182/v1/users URI 得到用戶列表,而後再經過用戶列表中所提供的 LINK 屬性,例如 <link>http://localhost:8182/v1/users/tester</link> 得到 tester 用戶的用戶信息。這樣的工做方式,很是相似於你在瀏覽器的某個頁面上點擊某個 hyperlink, 瀏覽器幫你自動定向到你想訪問的頁面,並不依賴任何第三方的信息 REST 構建的系統其系統的擴展能力要強於 SOAP,這能夠體如今它的統一接口抽象、代理服務器支持、緩存服務器支持等諸多方面, 而SOAP的成熟性能夠給須要提供給多開發語言的,多傳輸方式的,對於安全性要求較高的接口設計帶來便利。