徹底理解webservice SOAP WSDL

原文: http://wenku.baidu.com/view/f87b55f19e31433239689314.html


WebServices簡介

先給出一個概念 SOA ,即Service Oriented Architecture ,中文一般理解爲面向服務的架構,

既然說是一種架構的話,所以一般認爲 SOA 是包含了運行環境,編程模型,

架構風格和相關方法論等在內的一整套新的分佈式軟件系統構造方法和環境,

涵蓋服務的整個生命週期。而在 SOA 的架構風格中,服務是最核心的抽象手段。

SOA 中的服務是構建在一些列基於開放標準的基礎之上的,

Web 服務定義瞭如何在異構系統之間實現通信的標準化方法,

從而就使得 Web 服務可以跨越運行平臺和實現語言,

同時也使得 Web 服務成爲了實現 SOA 中服務的主要技術。

至於SOA 的話,太高深的技術,這裏不予討論(嘿嘿),本篇博文只介紹 WebServices 這項技術。

引子

有沒有一種辦法可以實現跨應用程序進行通信和跨平臺進行通信呢?

換句話說,就是有什麼辦法可以實現我的應用程序 A 可以和應用程序 B 進行通信呢?

或者說是,我用 Java 寫的應用程序和用 . Net 開發的應用程序之間進行通信呢?

很多時候,上面提到的這些,我們是必須要使用的,比如,一個跨應用程序吧,

拿騰訊 QQ 來說吧,我估計每一個人都用過騰訊 QQ 上面的天氣預報工具吧 ! ! !

上面的這個天氣預報功能是如何實現的呢?

有一種辦法,那就是騰訊公司放個衛星上天,並且在公司中成立一個氣象部門,天天關注於天氣,

然後每時每刻更新騰訊 QQ 上的這個天氣預報信息,

確實,這種辦法確實行得通,不過,要真這樣做的話,估計馬化騰也該被踢出去了(哪有這麼蠢啊?),

那麼上面這個是如何實現的呢?別急,且聽我慢慢道來~~~

然後,我們再來看看跨平臺這個東東又是什麼呢?

這裏主要是拿 . Net 平臺和Java 平臺來說明例子,

假若,有兩個公司,每個公司呢都有自己的一個項目,一個公司呢使用 . Net 開發,一個呢,使用 Java 開發,

恩,本來呢,這兩個是相互獨立的,進水不犯河水,但是有一天,突然,這兩個公司給合併了,

合併後的老總髮現,如果把兩個項目結合起來將會大大的賺一筆,爲此,如何做?

因爲要把兩個項目結合在一起,那麼這兩個項目之間總應該通通信吧 !!!

可這兩個項目又是基於不同的平臺,怎麼通信呢?麻煩了吧 !!!

而後再看一種情況,就是比如一個公司使用的服務器是 Windows Server 2008,

那麼它如何和 IT 供應商的UNIX 或者是 Linux 服務器進行連接呢?也很複雜吧 !!!

WebServices特點介紹

WebServices 提供一個建立分佈式應用的平臺,使得運行在不同操作系統和不同設備上的軟件,或者是用不同的程序語言和不同廠商的軟件開發工具開發的軟件,所有可能的已開發和部署的軟件,能夠利用這一平臺實現分佈式計算的目的。WebServices的思想是:使得應用程序也具有 Web 分佈式編程模型的鬆散耦合性。

WebServices的特點:

(1),WebServices 是自包含的。即在客戶端不需要附加任何軟件,只要客戶機支持 HTTP 和XML 就 OK 了。

(2),WebServices 是自我描述的。在客戶端和服務端都不需要知道除了請求和響應消息的格式和內容外的任何事。

(3),WebServices 是跨平臺和跨語言的。客戶端和服務端均可以在不同的平臺和語言環境中實現,同時,不必爲了支持 WebServices 而更改現有的代碼。

(4),WebServices 是基於開放和標準的。XML 和 HTTP 是WebServices 的主要技術基礎,而 XML 和HTTP 早就成了業內標準了。

(5),WebServices 是動態的。

(6),WebServices 是可以組合的。也就是通過一個 WebService 訪問另外一個 WebService 來達到組合的目的。通過組合 WebServices 便可以將簡單的 WebServices 聚合成爲實現更多複雜功能的複雜的服務。

(7),WebServices 是鬆散耦合的。它完全解耦了客戶端和服務端。

(8),WebServices 提供編程訪問的能力。換句話說,就是可以通過編寫程序來訪問Web 服務。

(9),WebServices 是基於經過考驗的成熟技術上構建的。比如 XML 和 HTTP。

(10),WebServices 提供打包現有應用程序的能力。

(11),WebServices 通過網絡進行發佈,查找和使用。

上面這些特點呢,現在不清楚的話,也不用緊,等下還會有詳細的說明的 !!!

WebServices到底是什麼?

如果簡單的說的話,WebServices就是一組函數庫,不過這和我們平時概念中的函數庫卻又有所不同,我們平時所使用的函數庫要麼是自己寫的(在自己的應用程序當中寫一組函數庫),

要麼是調用底層的 API(操作系統 API 如Win32 API),上面的這兩種情況有一個共同點,

那就是函數庫是位於客戶端本地的,比如,您調用 Win32 API的話,就是調用本地操作系統上的函數庫,而這裏提到 Web 服務也是一組函數庫這個概念和上面提到的函數庫這個概念的區別就在此處,因爲 Web服務看做一組函數庫的話,那麼這組函數庫不是位於本地的,而是位於遠程機器上(當然也可以是本地機器中)。

何爲 Web 服務?

也就是網絡服務,那就是把網絡上不知道那個地方的一些函數看做是一組服務,然後我再通過網絡就可以使用這些服務。

關於什麼是 Web 服務,上面的說法那是山寨版的,稍微正經一點的說法是:

Web 服務是一種部署在 Web 上的對象或者是應用程序組件。

Why WebServices

爲什麼需要使用 WebServices呢?這必須根據 WebServices 的特點以及其優勢進行分析了。

首先,上面呢,也說了,Web服務的話,就是一組網絡上的應用程序組件,

這樣的話,您便可以通過在您的應用程序中使用 Web 服務來將您的應用程序提升到服務層面上來。

既然可以看做是一組服務了的話,那麼當然就是可以提供給別個(別的應用程序)使用咯。

比如,我可以通過 Web 服務來公開一些接口給別個使用,至於這些要不要收費呢?那就看我心情了,前面舉了騰訊 QQ 上查詢天氣的例子,這個例子呢,就可以在這裏來做一個解釋了,

在中國,應該只有一個衛星來進行天氣預報的吧?騰訊也不可能爲了天氣預報而專門放個衛星上天吧?

可是騰訊 QQ 又確實是可以查詢天氣的,這裏,便可以通過 Web 服務來解決。

首先,中國氣象局應該是有一個衛星的,氣象局根據衛星所返回的結果實時發佈全國各地的天氣狀況,並且將這些天氣信息以 Web 服務的形式公開,然後呢,騰訊 QQ 便可以通過這個 Web 服務來訪問到天氣狀況了,再將這些天氣狀況反饋到 QQ 上就 OK 了。

然後,上面提到了 Web服務是應用程序組件,既然是組件,那麼就可以對這個組件重複的進行使用了,

同時可以通過 Web 服務來實現將這個應用程序組件作爲一個服務來進行使用,

更爲強大的是,可以將多個 WebServices組合成爲更爲強大的 WebServices ,

並且是通過互聯網哦!!!

這也是一大優點啊,

然後呢,最基本的 WebServices是基於 XML 和 HTTP 的

(當然這是最基本的 WebServices ,比如 WebServices 還可以通過 HTTPS 或者是 SMTP 來實現通信),

這又有什麼好處呢?很明顯,XML 和HTTP 這些都已經是標準了,

不論你是 Java 平臺呢,還是 . Net 平臺開發出來的(或者是是使用 Web 服務),既然我是使用 XML 和 HTTP 的話,我才懶得鳥你什麼 Java 還是 . Net 呢,我也不管你是 Linux 還是 Windows ,這一切都和我 Web 服務無關,

我關注的只是通過 HTTP 協議來傳輸 XML 就 OK 了,

至於這些 XML 是如何被服務提供者開發出來的或者這些 XML 是如何被服務請求者使用的,這些都和我無關,這裏便可以看出 Web 服務的另一個優勢了,那就是跨語言跨平臺(實現協同工作),所以可以通過 Web 服務來實現不同應用程序和不同平臺之間的通信。

Web 服務允許獨立於實現服務基於的硬件或者是軟件平臺和編寫服務所用的編程語言使用服務,

根據上面這兩點呢,

便可以解決掉最開始提出的使用 Java 開發的應用程序如何和使用 . Net 開發的應用程序之間進行通信這一問題,

同時,也可以解決 Linux 或者是UNIX 和 Windows Server 2008 之間進行連接這一問題了。

最後就是通過使用不同的 Web 服務,也不管 Web 服務是那種編程語言實現的,

我們都可以從不同的平臺和操作系統進行訪問,從而大大提高了不同應用程序共享數據和應用的能力。

並且 Web服務提供了構建 SOA 所必須得技術基礎。

從上面可以看出通過 WebServices解決了我們曾經想都不敢想的問題,這麼強大的東西爲什麼不加以好好利用呢?

           

          

           

WebServices體系結構

在Web 服務的體系結構中,涉及到三個角色,

一個是 Web 服務提供者,一個是 Web 服務中介者,還有一個就是 Web 服務請求者,

同時還涉及到三類動作,即發佈,查找,綁定,

Web 服務提供者:

可以發佈 Web 服務,並且對使用自身服務的請求進行響應,

Web 服務的擁有者,它會等待其他的服務或者是應用程序訪問自己。

Web 服務請求者:

也就是 Web 服務功能的使用者,它通過服務註冊中心也就是 Web 服務中介者查找到所需要的服務,

再利用 SOAP 消息向 Web 服務提供者發送請求以獲得服務。

Web 服務中介者:

也稱爲服務代理,用來註冊已經發布的 Web服務提供者,並對其進行分類,同時提供搜索服務,

簡單來說的話,Web 服務中介者的作用就是把一個 Web 服務請求者和合適的 Web 服務提供者聯繫在一起,

充當一個管理者的角色,一般是通過 UDDI來實現。

發佈:

通過發佈操作,可以使 Web服務提供者向 Web 服務中介者註冊自己的功能以及訪問的接口。

發現(查找):

使得 Web 服務請求者可以通過 Web 服務中介者來查找到特點的種類的 Web 服務。

綁定:

這裏就是實現讓服務請求者能夠使用服務提供者提供的服務了。

            

          

          

WebServices三種基本元素之 SOAP

SOAP 即 Simple Object AccessProtocol 也就是簡單對象訪問協議。

SOAP 呢,其指導理念是“唯一一個沒有發明任何新技術的技術”,

是一種用於訪問 Web 服務的協議。

因爲 SOAP 基於XML 和 HTTP ,其通過XML 來實現消息描述,然後再通過 HTTP 實現消息傳輸。

SOAP 是用於在應用程序之間進行通信的一種通信協議。

因爲是基於 XML 和HTTP 的,所以其獨立於語言,獨立於平臺,並且因爲 XML 的擴展性很好,

所以基於 XML 的 SOAP 自然擴展性也不差。

通過 SOAP 可以非常方便的解決互聯網中消息互聯互通的需求,

其和其他的 Web 服務協議構建起 SOA 應用的技術基礎。

SOAP 協議的一個重要特點是它獨立於底層傳輸機制,Web 服務應用程序可以根據需要選擇自己的數據傳輸協議,

可以在發送消息時來確定相應傳輸機制。

由於 HTTP 協議本身的一些特點和侷限性,

使得當 SOAP 使用HTTP 綁定的 Web 服務並不能滿足某些企業應用的需求。

比如,HTTP 不是一個可靠傳輸協議,所以有可能在傳輸過程中出現問題,

然後 HTTP 協議基於Request/Response 模型,也就是說客戶端需要在等待響應消息接收完成後才能繼續執行,

而此時如果響應時間過長呢?

基於上面的這些需求,便需要選擇合適的傳輸協議了。

關於這方面的內容的話,有點深奧了,有興趣的可以去看看 IBM 的一些關於這方面內容的介紹。

還有一點需要提及一下,那就是 SOAP 是可以繞過防火牆的,將來將會作爲 W3C 的標準進行發展。

            

          

          

WebServices三種基本元素之 WSDL

WSDL 即Web Services Description Language也就是 Web 服務描述語言。

是基於 XML的用於描述 Web 服務以及如何訪問 Web 服務的語言。

服務提供者通過服務描述將所有用於訪問 Web服務的規範傳送給服務請求者,

要實現 Web服務體系結構的鬆散耦合,服務描述是一個關鍵,

不管是請求者還是服務提供者,通過服務描述便可以不必瞭解對方的底層平臺,編程語言等,

服務描述與底層的 SOAP 基礎結構相結合,

足以封裝服務請求者的應用程序和服務提供者的 Web服務之間的這個細節。

WSDL 描述了 Web服務的三個基本屬性:

(1)服務所提供的操作

(2)如何訪問服務

(3)服務位於何處(通過 URL 來確定就 OK 了)

        

       

    

WebServices三種基本元素之 UDDI

UDDI 即 Universal Description,Discovery and Integration,也就是通用的描述,發現以及整合。

WSDL 呢,用來描述了訪問特定的 Web 服務的一些相關的信息,可以在互聯網上,

或者是在企業的不同部門之間,如何來發現我們所需要的 Web 服務呢?

而 Web 服務提供商又如何將自己開發的 Web 服務公佈到因特網上,

這就需要使用到 UDDI 了,UDDI的話,是一個跨產業,跨平臺的開放性架構,

可以幫助 Web 服務提供商在互聯網上發佈 Web 服務的信息。

UDDI 呢是一種目錄服務,企業可以通過 UDDI 來註冊和搜索 Web 服務。

簡單來時候話,UDDI 就是一個目錄,只不過在這個目錄中存放的是一些關於 Web 服務的信息而已。

並且 UDDI 通過SOAP 進行通訊,構建於 . Net 之上。

        

           

開發 Web服務的方式

(1)開發階段:

        實現一個 Web 服務,使這個 Web 服務能響應和接收 SOAP 消息,

      (這個呢,其實可以通過 Visual Studio 來幫助實現),

       定義好邏輯模塊(這個 Web 服務總要乾點事情吧),

       然後再撰寫 WSDL 文件(這個呢,開發工具會自動生成的,不需要人工撰寫了)

(2)部署階段:

       指定 Web 服務的傳輸協議,將 Web 服務註冊到相應服務描述部署文件(這些也是可以由工具來自動完成的)

(3)發佈階段:

       將 Web 服務的接口和調用的地址公開給客戶端調用,

       常用的發佈方式爲基於 Web 提供的WSDL 的鏈接,當然 UDDI 也是一個選擇。

         

          

     

總結一下 WebServices的優點

其實呢,前面介紹的都是關於 WebServices 的優點,在這裏就只是淺要的總結一下了。

首先,WebServices 是基於 Internet 和異構平臺的應用,

這樣便可以方便的實現通過網絡來通信,同時可以實現在不同的平臺之間共享數據。

然後就是,WebServices 是基於 XML 和HTTP 的,

也就是基於標準和開放的,基於 XML 的話,擴展性自然好,自然跨語言。

基於 HTTP 的話,自然跨平臺了。

最後,再回憶一下 WebServices 是一種應用程序組件吧,這樣便可以將 WebServices 重複使用了。

      談談 WebServices 的缺點

首先就是由於 XML 文件的難以解析,所以在使用 Web 服務的時候,會消耗較多的 CPU 和內存資源,

而後,SOAP 是基於XML 的,所以在網絡傳輸中傳輸的是 XML 文件,

但是由 XML 文件相比於二進制文件來說,要大很多,自然就會消耗更多的網絡資源了。

而後,由於通過 WSDL 解耦了Web 服務提供者和請求者,且 SOAP 消息時從發送者向接收者單向傳送的,

這在一定程度上造成了 WebServices 是一種無狀態服務,

儘管現在在 . Net 中可以通過 Session 來實現在客戶端和服務端共享一些數據,

但是單單依靠 Session 來實現客戶端和服務端的狀態交互也太牽強了吧

WebServices 在數據綁定上也存在一些缺陷,

因爲所有的數據在傳輸中都是使用的 XML 來實現的,

因此,需要在二進制數據和 XML 之間進行一個轉換(通過序列化和反序列化來實現),

而在轉換過程中有可能出現語義丟失的情況。

最後就是 WebServices 的技術要求相對比較高,

因爲涉及到底層的 HTTP 協議以及SOAP ,WSDL 和UDDL 這三大平臺元素,

所以學習的曲線也是比較長的,

當然,在 . Net 中可以通過 Visual Studio 非常快速和簡單的開發和訪問一個 Web 服務,

但這只限於在簡單的使用上,而對於本質的東西,是比較難的。

後續

正如題目所言,是 WebServices 簡介,既然是簡介的話,那麼自然就是以簡爲目標了,

說明一下的是,上面的這篇博文呢,源自前幾天做的一個關於 WebServices 的演講,

演講的 PPT 還存有,有興趣要的可以留個郵箱的。

          

          

        

. Net中 WebServices 的實戰

下面呢,就來具體看看在 . Net中如何開發一個WebServices 以及如何使用這個 WebServices

開發環境:

Windows 7 下IIS 7.5

Visual Studio TeamSystem 2008

Sql Server 2008

首先來看看如何開發一個 WebServices

先建立一個 ASP.NET 應用程序項目,然後再在項目中添加一個 WebServices 服務,

然後就是在這個 WebServiceTest中編寫業務邏輯了,

本次實例的業務邏輯呢就是從數據庫“圖書館管理系統”中取出所有的讀者的信息。

WebServiceTest.asmx中的代碼如下

usingSystem.Web.Services;
usingSystem.Data; 
usingSystem.Data.SqlClient; 
usingSystem.Web.Configuration;

namespace WebServiceDemo

    [WebService(Namespace = "
http://tempuri.org/")]
   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]

    public classWebServiceTest :System.Web.Services.WebService
    { 
        
[WebMethod] 
       public DataSet GetAllReader()
        { 
            
DataSet ds = newDataSet();
           string connStr =
               WebConfigurationManager.ConnectionStrings["DBConnString"].ConnectionString;
            string 
sqlStr = "SELECT[ReaderID],[ReaderIDType],[ReaderName]," +
                                  "[ReaderSex],[ReaderBirth]" + 
                           "FROM [
圖書館管理系統].[dbo].[Reader]";
            
using (SqlConnection sqlCon = new SqlConnection(connStr))
            { 
               
using (SqlCommand sqlCom =sqlCon.CreateCommand())
               { 
                   sqlCom.CommandType = CommandType.Text; 
                   sqlCom.CommandText = sqlStr; 
                  
using (SqlDataAdapter sqlDa = newSqlDataAdapter(sqlCom))
                   { 
                       sqlDa.Fill(ds); 
                   } 
               } 
            } 
            
return ds;
        } 
    } 
}

然後我再在這一個項目 WebServiceDemo中添加一個頁面 Test . aspx

來實現訪問自身應用程序中的 WebServices

(Test. aspx和 WebServiceTest . asmx 位於同一應用程序中)

這個 Test . aspx 呢非常簡單,僅僅在上面放了一個 GridView ,然後稍微寫點 Code-Behind 就 OK 了,

其代碼如下:

using System;

namespace WebServiceDemo

    public partial class Test : System.Web.UI.Page 
    { 
        protected void Page_Load(objectsender, EventArgs e) 
        { 
            if(!IsPostBack) 
            { 
               
WebServiceTesttest= new WebServiceTest();
               GridView1.DataSource = 
test.GetAllReader();
               GridView1.DataBind(); 
            } 
        } 
    } 
}

再來瀏覽一下 Test . aspx頁面

可以看出已經達到了預定的效果,也就是從數據庫中通過 WebServices取出了數據。

而從上面的代碼可以看出,僅僅是將 WebServices看做是一個類了,

將其作爲一個類來進行使用(實質上也就是一個類而已)。

下面我們還需要看一種情況,

那就是,實現在另外的一個應用程序中訪問上面建立的 WebServices

其實這種情況呢,就是和訪問網絡上的 WebServices 一樣了,

比如騰訊 QQ 就是使用這種方式來實現的,

爲了模擬這種實現,我首先將上面建立的這個 ASP.NET 應用程序 部署到 IIS 上面,

且指定了一個端口爲 81

       

然後我再建立一個項目 TestWebServices

並且在這個項目裏面也添加一個頁面 Test . aspx

在Test . aspx 上也只放一個 GridView 控件。

然後就要給這個項目添加 Web服務的引用了(右鍵TestWebService 點擊“添加 Web 引用”)

如果您要訪問的是互聯網上的 Web服務,比如查詢天氣,

那麼就需要在上面的 URL中寫入 Web 服務所在的地址,然後“前往”就 OK 了,

由於本次的演示,我只是把我的 Web服務放在了本地的 IIS 上面,

所以在此處呢選擇“本地計算機上的 Web服務”,

從上面的截圖中就可以看出,在 81號端口上面我有一個 Web 服務,

就是前面的 Demo中建立的 Web 服務 WebServiceTest

然後我選擇這個 Web 服務,單擊它即可,

上面的這幅截圖中便可以看出我在 Web 服務WebServiceTest 中公開的接口了,

由於我只在其中寫了一個接口 GetAllReader ,所以在這裏便只顯示了一個了。

在這一步中,您便可以添加這個 Web 引用了,不過要注意的是,

如果在這一步添加 Web 引用的話,那麼這個 Web 服務中所有被公開的方法都會被添加到您的項目中,

比如,如果我在上面的 Web 服務中還有一個 GetAllName 的方法的話,

那麼在這一步添加 Web 引用的話,就會將 GetAllReader 和 GetAllName 全部添加到您的項目當中,

但是有時候,這樣會太浪費了,因爲我可能根本就不需要使用 GetAllName 而只需要 GetAllReader,

此時,可以單擊上面的 GetAllReader 進入下一步,

在這一步中添加 Web 引用的話,那麼就只會在項目中添加 GetAllReader 這個方法的引用了,

我們在這裏使用這種方法來添加 GetAllReader 的引用。

單擊“添加引用”,此時可以看到在項目中生成一些文件,

(這裏呢,其實就是代理模式來實現了)

既然在項目中引用了這個 Web服務了,

那麼下一步就是在 Test . aspx中使用這個 Web 服務了。

看看 Test . aspx的 Code-Behind 吧

using System;

namespace TestWebService

    public partial class Test : System.Web.UI.Page 
    { 
        protected void Page_Load(objectsender, EventArgs e) 
        { 
            if(!IsPostBack) 
            { 
             
   //WebServiceTest.GetAllReader 這一段是我引用後的服務名 
               
WebServiceTest.GetAllReader.WebServiceTesttest =
                   new 
WebServiceTest.GetAllReader.WebServiceTest();
               GridView1.DataSource = test.GetAllReader();
               GridView1.DataBind(); 
            } 
        } 
    } 
}

下面就來看一看效果了

從上面的效果便可以看出,我們已經成功在另外的應用程序中訪問了 Web 服務,

也可以得出 Web 服務實現了在不同應用程序之間數據的共享。

如果,讀者對通過網絡 URL 來訪問WebServices 有疑問的話,

可以參考一下筆者的另外一篇稍微帶有 WebServices 性質的博文,

在其中實現了一個訪問互聯網上提供的天氣查詢 Web 服務。

http://www.cnblogs.com/QinBaoBei/archive/2010/03/30/1700898.html

上面呢,通過幾個 Demo 對WebServices 在 .Net 中的實戰進行了一個簡單的應用了。

在這裏一切似乎都和前面所提到的 SOAP ,WSDL,UDDI 均扯不上關係,

其實不然,只不過這些全部都由別個(工具)給你完成了,而你只是簡單的開發一下邏輯就 OK 了,

不過呢,簡單歸簡單,理解前面的一些原理還是很有必要的。

這裏還點一下,就是上面呢,我通過 WebServices 來查詢數據庫並且返回一個 DataSet,

不過,大家有沒有想過,如果這個 DataSet 中的數據量有很大呢,比如 100萬條,甚至更多,

這樣的話,在網絡傳輸中那不慢的要死啊,其實有一種比較好的解決辦法,那就是壓縮,

關於壓縮呢,又有好幾種方法,比如 GZIP 可以將其壓縮到原來的一半以上,

這幾種方法各有所長,一個晚上又過咯,很晚啦,以後有時間的話,可能會寫一篇這方面的博文吧 !!!

關於WebServices 的簡介就到這裏了 !!!


WebService的兩種方式SOAP和REST比較 

我的讀後感:由於第一次接觸WebService,對於很多概念不太理解,尤其是看到各個OpenAPI的不同提供方式時,更加疑惑。如google map api採用了AJAX方式,通過javascript提供API,而淘寶TOP則採用直接的HTTP+XML請求方式,最令我疑惑的是教材上講的WSDL,UDDI從沒有在這些API中出現過。現在知道了WebService原來有兩種方式,一是SOAP協議方式,在這種方式下需要WSDL,UDDI等,二是REST方式,這種方式根本不需要WSDL,UDDI等。而且REST方式現在看來是更加流行,更有前途的方式。 
       在SOA的基礎技術實現方式中WebService佔據了很重要的地位,通常我們提到WebService第一想法就是SOAP消息在各種傳輸協議上交互。近幾年REST的思想伴隨着SOA逐漸被大家接受,同時各大網站不斷開放API提供給開發者,也激起了REST風格WebService的熱潮。 
       在收到新需求Email之前,我對REST的理解僅僅是通過半懂不懂的看了Fielding的REST博士論文,說實話當時也就是希望瞭解這麼一個新概念,對於其內部的思想只是很膚淺的瞭解了一下。 
       ASF的最新需求就是可能需要實現REST風格的WebService集成,因此不得不好好的去看看REST的真正思想含義以及當前各大網站的設計方式。後面所要表述的也是我這個初學者的一些看法和觀點,拋磚引玉,希望在我將REST融入到ASF之前能夠獲得更多的反饋和意見。 

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協議就可以實現,開發者也會受益於這種輕量級的協議。 
       自己理解的將REST的思想歸結以下有如下幾個關鍵點: 
       
1.面向資源的接口設計 
所有的接口設計都是針對資源來設計的,也就很類似於我們的面向對象和麪向過程的設計區別,只不過現在將網絡上的操作實體都作爲資源來看待,同時URI的設計也是體現了對於資源的定位設計。後面會提到有一些網站的API設計說是REST設計,其實是RPC-REST的混合體,並非是REST的思想。 

       2.抽象操作爲基礎的CRUD 
       這點很簡單,Http中的get,put,post,delete分別對應了read,update,create,delete四種操作,如果僅僅是作爲對於資源的操作,抽象成爲這四種已經足夠了,但是對於現在的一些複雜的業務服務接口設計,可能這樣的抽象未必能夠滿足。其實這也在後面的幾個網站的API設計中暴露了這樣的問題,如果要完全按照REST的思想來設計,那麼適用的環境將會有限制,而非放之四海皆準的。       

       3.Http是應用協議而非傳輸協議 
       這點在後面各大網站的API分析中有很明顯的體現,其實有些網站已經走到了SOAP的老路上,說是REST的理念設計,其實是作了一套私有的SOAP協議,因此稱之爲REST風格的自定義SOAP協議。 

4.無狀態,自包含 
這點其實不僅僅是對於REST來說的,作爲接口設計都需要能夠做到這點,也是作爲可擴展和高效性的最基本的保證,就算是使用SOAP的WebService也是一樣。 


REST vs SOAP 
成熟度: 
SOAP雖然發展到現在已經脫離了初衷,但是對於異構環境服務發佈和調用,以及廠商的支持都已經達到了較爲成熟的情況。不同平臺,開發語言之間通過SOAP來交互的web service都能夠較好的互通(在部分複雜和特殊的參數和返回對象解析上,協議沒有作很細緻的規定,導致還是需要作部分修正) 
REST國外很多大網站都發布了自己的開發API,很多都提供了SOAP和REST兩種Web Service,根據調查部分網站的REST風格的使用情況要高於SOAP。但是由於REST只是一種基於Http協議實現資源操作的思想,因此各個網站的REST實現都自有一套,在後面會講訴各個大網站的REST API的風格。也正是因爲這種各自實現的情況,在性能和可用性上會大大高於SOAP發佈的web service,但統一通用方面遠遠不及SOAP。由於這些大網站的SP往往專注於此網站的API開發,因此通用性要求不高。 
ASF上考慮發佈REST風格的Web Service,可以參考幾大網站的設計(兄弟公司的方案就是參考了類似於flickr的設計模式),但是由於沒有類似於SOAP的權威性協議作爲規範,REST實現的各種協議僅僅只能算是私有協議,當然需要遵循REST的思想,但是這樣細節方面有太多沒有約束的地方。REST日後的發展所走向規範也會直接影響到這部分的設計是否能夠有很好的生命力。 
總的來說SOAP在成熟度上優於REST。 

效率和易用性: 
       SOAP協議對於消息體和消息頭都有定義,同時消息頭的可擴展性爲各種互聯網的標準提供了擴展的基礎,WS-*系列就是較爲成功的規範。但是也由於SOAP由於各種需求不斷擴充其本身協議的內容,導致在SOAP處理方面的性能有所下降。同時在易用性方面以及學習成本上也有所增加。 
       REST被人們的重視,其實很大一方面也是因爲其高效以及簡潔易用的特性。這種高效一方面源於其面向資源接口設計以及操作抽象簡化了開發者的不良設計,同時也最大限度的利用了Http最初的應用協議設計理念。同時,在我看來REST還有一個很吸引開發者的就是能夠很好的融合當前Web2.0的很多前端技術來提高開發效率。例如很多大型網站開放的REST風格的API都會有多種返回形式,除了傳統的xml作爲數據承載,還有(JSON,RSS,ATOM)等形式,這對很多網站前端開發人員來說就能夠很好的mashup各種資源信息。 
       因此在效率和易用性上來說,REST更勝一籌。 

安全性: 
       這點其實可以放入到成熟度中,不過在當前的互聯網應用和平臺開發設計過程中,安全已經被提到了很高的高度,特別是作爲外部接口給第三方調用,安全性可能會高過業務邏輯本身。 
       SOAP在安全方面是通過使用XML-Security和XML-Signature兩個規範組成了WS-Security來實現安全控制的,當前已經得到了各個廠商的支持,.net ,php ,java 都已經對其有了很好的支持(雖然在一些細節上還是有不兼容的問題,但是互通基本上是可以的)。 
       REST沒有任何規範對於安全方面作說明,同時現在開放REST風格API的網站主要分成兩種,一種是自定義了安全信息封裝在消息中(其實這和SOAP沒有什麼區別),另外一種就是靠硬件SSL來保障,但是這隻能夠保證點到點的安全,如果是需要多點傳輸的話SSL就無能爲力了。安全這塊其實也是一個很大的問題,今年在BEA峯會上看到有演示採用SAML2實現的網站間SSO,其實是直接採用了XML-Security和XML-Signature,效率看起來也不是很高。未來REST規範化和通用化過程中的安全是否也會採用這兩種規範,是未知的,但是加入的越多,REST失去它高效性的優勢越多。 

應用設計與改造: 
       我們的系統要麼就是已經有了那些需要被髮布出去的服務,要麼就是剛剛設計好的服務,但是開發人員的傳統設計思想讓REST的形式被接受還需要一點時間。同時在資源型數據服務接口設計上來說按照REST的思想來設計相對來說要容易一些,而對於一些複雜的服務接口來說,可能強要去按照REST的風格來設計會有些牽強。這一點其實可以看看各大網站的接口就可以知道,很多網站還要傳入function的名稱作爲參數,這就明顯已經違背了REST本身的設計思路。 
       而SOAP本身就是面向RPC來設計的,開發人員十分容易接受,所以不存在什麼適應的過程。 

總的來說,其實還是一個老觀念,適合的纔是最好的 
       技術沒有好壞,只有是不是合適,一種好的技術和思想被誤用了,那麼就會得到反效果。REST和SOAP各自都有自己的優點,同時如果在一些場景下如果去改造REST,其實就會走向SOAP(例如安全)。 
       REST對於資源型服務接口來說很合適,同時特別適合對於效率要求很高,但是對於安全要求不高的場景。而SOAP的成熟性可以給需要提供給多開發語言的,對於安全性要求較高的接口設計帶來便利。所以我覺得純粹說什麼設計模式將會佔據主導地位沒有什麼意義,關鍵還是看應用場景。 
       同時很重要一點就是不要扭曲了REST現在很多網站都跟風去開發REST風格的接口,其實都是在學其形,不知其心,最後弄得不倫不類,性能上不去,安全又保證不了,徒有一個看似象摸象樣的皮囊。 

REST設計的幾種形式 
參看了幾個大型網站的REST風格的API設計,這裏做一下大致的說明: 

FaceBook: 

請求消息: 
       在URI設計上採取了類似於REST的風格。例如對於friends的獲取,就定義爲friends.get,前面部分作爲資源定義,後面是具體的操作,其他的API也是類似,資源+操作,因此就算使用http的get方法都可能作了update的操作,其實已經違背了REST的思想,但是說到,其實那麼複雜的業務接口設計下,要通過RUCD來抽象所有的接口基本是不實際的。在URI定義好以後,還有詳細的參數定義,包括類型以及是否必選。 

響應消息: 
       有多種方式,XML,JSON。XML有XSD作爲參考。有點類似於沒有Head的SOAP,只不過這裏將原來可以定義在WSDL中的XSD抽取出來了。 

Flickr: 
       請求消息: 
       http://api.flickr.com/services/rest/?method=flickr.test.echo&name=value 
       這裏就可以很明顯看出它所定製的REST請求其實和RPC沒有什麼太大的區別。 
       
       消息返回: 
正確處理返回 
<?xml version="1.0" encoding="utf-8" ?> 
<rsp stat="ok"> 
         [xml-payload-here] 
</rsp> 
錯誤處理返回 
<?xml version="1.0" encoding="utf-8" ?> 
<rsp stat="fail"> 
         <err code="[error-code]" msg="[error-message]" /> 
</rsp> 
       根據返回可以看出已經違背了REST的思想,還是把Http協議作爲傳輸承載協議,並沒有真正意義上使用Http協議作爲資源訪問和操作協議。 
       總的來說,只是形式上去模仿REST,自己搞了一套私有協議。 

Ebay: 
       請求消息: 
       採用xml作爲承載,類似於SOAP,不過去除SOAP消息的封裝和包頭,同時在請求中附加了認證和警告級別等附加信息。 
       消息返回: 
       類似於SOAP消息,不過刪除了SOAP的封裝和包頭,同時在返回結構中增加了消息處理結果以及版本等附加信息。 
       這個很類似於當前Axis2框架的做法,將SOAP精簡,同時根據自身需求豐富了安全,事務等協議內容。 

Yahoo Maps: 
       請求消息: 
       
       採用REST推薦的方式,URI+Parameters。 
       返回消息: 
<?xml version="1.0" encoding="UTF-8"?> 
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="urn:yahoo:maps" 
xsi:schemaLocation="urn:yahoo:maps http://local.yahooapis.com/MapsService/V1/GeocodeResponse.xsd"> 
<Result precision="address"> 
    <Latitude>37.416384</Latitude> 
    <Longitude>-122.024853</Longitude> 
    <Address>701 FIRST AVE</Address> 
    <City>SUNNYVALE</City> 
    <State>CA</State> 
    <Zip>94089-1019</Zip> 
    <Country>US</Country> 
</Result> 
</ResultSet> 
SOAP的精簡xml返回,其他信息,例如出錯碼等信息由Http協議頭來承載。 

YouTube: 
請求消息: 
可以看到對於資源操作的URI定義也是參數的一部分。 
返回消息: 
<?xml version="1.0" encoding="utf-8"?> 
<ut_response status="ok"> 
    <user_profile> 
        <first_name>YouTube</first_name> 
        <last_name>User</last_name> 
        <about_me>YouTube rocks!!</about_me> 
        <age>30</age> 
        <video_upload_count>7</video_upload_count> 
    </user_profile> 
</ut_response> 
       自定義的類SOAP消息。 

Amazon: 
       請求消息: 
       https://Amazon FPS web service end point/?AWSAccessKeyId=Your AWSAccessKeyId 
      &Timestamp=[Current timestamp] &Signature=[Signature calculated from hash of Action and Timestamp] 
      &SignatureVersion=[Signature calculated from hash of Action and Timestamp] 
      &Version=[Version of the WSDL specified in YYYY-MM-DD format] &Action=[Name of the API] 
      &parameter1=[Value of the API parameter1] &parameter2=[Value of the API parameter2] 
      &...[API parameters and their values] 
       返回消息: 
       類似於SOAP的自有協議,消息體中包含了消息狀態等附加信息。 

總結: 
       看了上面那麼多網站的設計,總結一下主要有這麼幾種設計方式。 

請求消息設計: 
1. 基本符合REST標準方式:資源URI定義(資源.操作)+參數。這類設計如果濫用get去處理其他類型的操作,那麼和2無異。 
2. REST風格非REST思想:資源URI定義+參數(包含操作方法名)。其實就是RPC的REST跟風。 
3. 類似於SOAP消息,自定義協議,以xml作爲承載。(可擴展,例如鑑權,訪問控制等),不過那就好比自己定義了一套SOAP和SOAP extends。大型的有實力的網站有的採取此種做法。 

響應消息設計: 
1.       REST標準方式,將Resource State傳輸返回給客戶端,Http消息作爲應用協議而非傳輸協議 
2.       以XML作爲消息承載體,Http作爲消息傳輸協議,處理狀態自包含。 
3.       自定義消息格式,類似於SOAP,提供可擴展部分。 

作爲遵循REST的理念來看我的選擇是響應1和請求1的設計。 


REST和ASF的集成 
ASF要集成REST就現在來看有兩種比較合適的方法。 
一.就是採用Axis2的REST實現,這種方式的好處就是開發週期短,容易集成,但是請求和響應的格式無法改變,資源URI設計受限,Axis2的REST其實就是將SOAP消息精簡,請求的時候刪除了SOAP的頭,響應的時候僅僅返回資源信息,如果提供xsd就可以被各種客戶端所解析。並非真正的REST。 
二.就是採用Restlet開源框架,將Restlet開源框架集成到ASF中,由於Restlet本身就是可內嵌的應用框架,因此集成不成問題,同時Restlet框架只是API結構框架,因此實現和定義完全分開,集成Restlet以後可以自己實現其中的解析引擎也可以採用默認提供的引擎,同時對於內嵌Jetty等多種開源項目的支持,將更多優勢融入到了Rest中。看了一下國內也有很多朋友已經關注Restlet開源項目,看了它的架構設計,個人覺得還是比較靈活和緊湊的。 

題外話 
       在寫這篇文章以前寫了一篇調研報告羣發給各個架構師們參考,期待反饋。下午正好和我們的首席架構師聊了一會兒。其實我和他的感覺是一樣的,REST是否真的在我們現有的服務框架中需要集成,理解了REST的思想再去看應用場景,那麼可以發現如果要完全遵循REST的設計理念來設計接口的話,那麼強要去改變現有已經存在的或者還未開發的接口就會落入爲了技術而技術,爲了潮流而跟風的近地。當然並不否認REST的好,其實我們兄弟公司的一些業務場景有部分的接口十分合適這類設計,面向資源,高效,簡潔,易用都能夠體現出它的價值。我們將會和我們的兄弟公司合作,也會參考他們的設計理念,在參考當前各個網站的實現情況下,部分的採用這類形式的發佈,提供給第三方的ISV,無疑是我現在把REST融入到ASF中最好的理由。 
       有了需求去做纔不會陷入爲了技術而技術,畢竟技術是由商業價值驅動的,同樣社會上充斥着各種技術的鼓吹,如果稍不留神就會陷入跟風的潮流中。





發佈了4 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章