主題:實戰WebService II: SOAP篇(基於php)

概述(SOAP和XML-PRC比較) php

在Web服務發展的初期,XML格式化消息的第一個主要用途是,應用於XML-RPC協議,其中RPC表明遠程過程調用。在XML遠程過程調用 (XML-RPC)中,客戶端發送一條特定消息,該消息中必須包括名稱、運行服務的程序以及輸入參數。

  XML-RPC只能使用有限的數據類型種類和一些簡單的數據結構。人們認爲這個協議還不夠強大,因而就出現了SOAP——其最初的定義是簡單 對象訪問協議。以後,你們逐漸意識到SOAP其實並不簡單,並且也不須要必須使用面嚮對象語言,因此,如今人們只是沿用SOAP這個名稱而已。

  XML-RPC只有簡單的數據類型集,取而代之,SOAP是經過利用XML Schema的不斷髮展來定義數據類型的。同時,SOAP也可以利用XML 命名空間,這是XML-RPC所不須要的。如此一來,SOAP消息的開頭部分就能夠是任何類型的XML命名空間聲明,其代價是在系統之間增長了更多的複雜 性和不兼容性。

  隨着計算機行業的覺醒,人們發現了基於XML的Web服務的商業潛力,因而,各家公司開始不斷地發掘想法、觀點、論據以及標準化嘗試。W3C 曾經設法以「Web服務活動」的名義來組織成果展,其中也包括實際作出SOAP的XML協議工做組(XML Protocol Working Group)。與Web服務有關的標準化成果(從某種程度上說與SOAP相關或者依賴於SOAP)的數量已經倍增了到了使人驚訝的程度。

  最初,SOAP是做爲XML-RPC的擴展而發展起來的,它主要強調的是,經過從WSDL文件中所得到的方法和變量名來進行遠程過程調用。現 在,經過不斷進步,人們發現了更多的使用SOAP的方式,而不只僅是採用「文件」方式——基本上是使用一個SOAP信封來傳送XML格式化文件。不管如 何,要掌握SOAP,瞭解WSDL所扮演的角色是最根本的。
git

SOAP數據包結構解析 web

SOAP的消息被稱爲一個SOAP Envelope,包括SOAP Header和SOAP Body。其中,SOAP Header能夠方便的插入各類其它消息來擴充Web Service的功能,好比Security(採用證書訪問Web Service),SOAP Body則是具體的消息正文,也就是Marshall後的信息。

SOAP調用的時候,也就是向一個URL(好比 http://api.google.com/search/beta2 )發送HTTP Post報文(根據SOAP規範,HTTP Get報文也可被支持),調用方法的名字在HTTP Request Header SOAP-Action中給出,接下來就是SOAP Envelope了。服務端接到請求,執行計算,將返回結果Marshall成XML,用HTTP返回給客戶端。

如下[是移動MISC接入]Wap1.6業務訂購數據包樣例api

MISC1.6的業務訂購關係同步的請求包
數據結構

 

    <?xml version="1.0" encoding="utf-8" ?>   
    <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
                       xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
                       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"   
                       xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">  
      <SOAP-ENV:Header>  
        <TransactionID xmlns="http://10.1.2.122/misc/dsmp.xsd">  
    00110100037392</TransactionID>   
      </SOAP-ENV:Header>  
      <SOAP-ENV:Body>  
        <SyncOrderRelationReq xmlns="http://10.1.2.122/misc/dsmp.xsd">  
          <Version>1.5.0</Version>   
          <MsgType>SyncOrderRelationReq</MsgType>   
          <Send_Address>  
            <DeviceType>0</DeviceType>   
            <DeviceID>0011</DeviceID>   
          </Send_Address>  
          <Dest_Address>  
            <DeviceType>400</DeviceType>   
            <DeviceID>0</DeviceID>   
          </Dest_Address>  
          <FeeUser_ID>  
            <UserIDType>2</UserIDType>   
            <MSISDN />   
            <PseudoCode>00116000000286</PseudoCode>   
          </FeeUser_ID>  
          <DestUser_ID>  
            <UserIDType>2</UserIDType>   
            <MSISDN />   
            <PseudoCode>00116000000286</PseudoCode>   
          </DestUser_ID>  
          <LinkID>SP</LinkID>   
          <ActionID>1</ActionID>   
          <ActionReasonID>1</ActionReasonID>   
          <SPID>919102</SPID>   
          <SPServiceID>0000000064</SPServiceID>   
          <AccessMode>2</AccessMode>   
          <FeatureStr />   
        </SyncOrderRelationReq>  
      </SOAP-ENV:Body>  
    </SOAP-ENV:Envelope>  

 

MISC1.6的業務訂購關係同步的響應包:ide

 

    <?xml version="1.0" encoding="utf-8"?>  
    <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
             xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"   
             xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">  
      <SOAP-ENV:Header>  
        <TransactionID xmlns="http://www.monternet.com/dsmp/schemas/">  
    00110100037392</TransactionID>  
      </SOAP-ENV:Header>  
      <SOAP-ENV:Body>  
        <SyncOrderRelationResp xmlns="http://www.monternet.com/dsmp/schemas/">  
          <Version>1.5.0</Version>  
          <MsgType>SyncOrderRelationResp</MsgType>  
          <hRet>0</hRet>  
        </SyncOrderRelationResp>  
      </SOAP-ENV:Body>  
    </SOAP-ENV:Envelope>  

 

實戰SOAPI 函數

如今作SOAP開發通常有三種方式選擇
    * PEAR自帶的soap擴展,
    * PHP自帶的SOAP擴展,
    * NuSOAP(純PHP,彷佛已通過時)
注:還有WSO2.org(關於WSO2.org能夠考慮嘗試一下)

PHP 5 中新增了內置的 SOAP 擴展,咱們稱之爲 ext/soap。它是做爲 PHP 的一部分提供的,所以不須要下載、安裝和管理單獨的包。這是第一個用 C 而不是 PHP 爲 PHP 編寫的 SOAP 實現,所以做者聲稱它的速度要快得多。

由於新的擴展是 PHP 的完整組成部分之一,相關文檔包含在 PHP 手冊的 Function Reference 部分(php_soap.dll)。

SOAP 參考是以一個重要的免責聲明開始的:

警告:該擴展是試驗性的(EXPERIMENTAL)。本擴展的行爲,包括關於本擴展的函數名和其餘內容,在之後的 PHP 版本中隨時可能改變,不另行通知。使用該擴展的風險自負。

警告看起來有點讓人擔憂,但實際上這個擴展彷佛獲得了很好的支持。和任何新代碼同樣,該擴展也存在缺陷,可是報告的問題一般很快就能獲得修正。在 PHP 站點上能夠看到缺陷列表。咱們估計,在未來的 PHP 版本中,該擴展將從試驗性功能轉爲主流功能
工具

一個訪問.NET WEB服務的客戶端例子 post

    <?php  
       
    $objSoapClient = new SoapClient("http://www.webservicemart.com/uszip.asmx?WSDL");  
       
    $param=array("ZipCode"=>'12209');  
    $out=$objSoapClient->ValidateZip($param);  
    $data=$out->ValidateZipResult;  
    echo $data;  
    ?>  

運行後輸出學習

    <result code="200"><item zip="12209" state="NY"   
    latitude ="42.64081" longitude ="-73.7856"/></result>  

在實驗的過程中,使用了一個抓包工具Wireshark來分析報文。Wireshark很不錯,在Filter處設置ip.addr == 208.109.78.12(208.109.78.12 是 www.webservicemart.com 的IP),而後啓動監控,能夠分析上述調用過程當中HTTP包是什麼樣的。

實戰SOAPII
用PHP創建SOAP服務

創建soap_server.php(虛擬路徑爲:http://172.16.0.24/php/soap/soap_server.php)

<?php
/**
* A simple math utility class
* @author John Coggeshall john@zend.com
 */
class math {
  /**
   * Add two integers together
  *
  * @param integer $a The first integer of the addition
  * @param integer $b The second integer of the addition
  * @return integer The sum of the provided integers
   */
  public function add($a, $b) {
    return $a + $b;
  }
 
 /**
  * Subtract two integers from each other
  *
  * @param integer $a The first integer of the subtraction
  * @param integer $b The second integer of the subtraction
  * @return integer The difference of the provided integers
  */
  public function sub($a, $b) {
    return $a - $b;
  }
 
 /**
  * Div two integers from each other
  *
  * @param integer $a The first integer of the subtraction
  * @param integer $b The second integer of the subtraction
  * @return double The difference of the provided integers
  */
  public function div($a, $b) {
    if($b == 0) {
      throw new SoapFault(-1, "Cannot divide by zero!");
    }
    return $a / $b;
  }  
}
  $server = new SoapServer('math.wsdl', array('soap_version' => SOAP_1_2));
  $server->setClass("math");
  $server->handle();
 
?>

注意幾點:

         
    1. math類是即將公開的webservice.
    2.    
    3. 注$server→setClass,不是$server→addClass

 

用PHP客戶端訪問剛創建SOAP服務

 

    <?php  
      //$client = new SoapClient('http://localhost/php/soap/math.wsdl');   
      $client = new SoapClient("http://localhost/php/soap/soap_server.php?WSDL");  
      try {  
        $result = $client->div(8, 2); // will cause a Soap Fault if divide by zero  
        print "The answer is: $result";  
      } catch(SoapFault $e) {  
        print "Sorry an error was caught executing your request: {$e->getMessage()}";  
      }  
    ?>  

 

本質上,http://localhost/php/soap /soap_server.php?WSDL就是要訪問到註釋行所指的wsdl描述文件,因此這個WSDL文件必須事先生成。而對於其餘語言如Java則 能夠動態生成。我目前的學習發現對於php自帶的SOAP擴展要求這個WSDL文件必須事先生成好。

能夠用ZendStudio生成靜態的WSDL文件,此時用到math類的phpdoc做爲生成WSDL的元數據。 用ZendStudio生成wsdl文件時,必須正確說明web服務目標地址,片段以下:

    ...  
        <service name="mathService">  
            <port name="mathPort" binding="typens:mathBinding">  
                <soap:address location="http://localhost/php/soap/soap_server.php"/>  
            </port>  
        </service>  
    ....  
   發表時間:2007-12-31  
PHP
概述(SOAP和XML-PRC比較)

在Web服務發展的初期,XML格式化消息的第一個主要用途是,應用於XML-RPC協議,其中RPC表明遠程過程調用。在XML遠程過程調用 (XML-RPC)中,客戶端發送一條特定消息,該消息中必須包括名稱、運行服務的程序以及輸入參數。

  XML-RPC只能使用有限的數據類型種類和一些簡單的數據結構。人們認爲這個協議還不夠強大,因而就出現了SOAP——其最初的定義是簡單 對象訪問協議。以後,你們逐漸意識到SOAP其實並不簡單,並且也不須要必須使用面嚮對象語言,因此,如今人們只是沿用SOAP這個名稱而已。

  XML-RPC只有簡單的數據類型集,取而代之,SOAP是經過利用XML Schema的不斷髮展來定義數據類型的。同時,SOAP也可以利用XML 命名空間,這是XML-RPC所不須要的。如此一來,SOAP消息的開頭部分就能夠是任何類型的XML命名空間聲明,其代價是在系統之間增長了更多的複雜 性和不兼容性。

  隨着計算機行業的覺醒,人們發現了基於XML的Web服務的商業潛力,因而,各家公司開始不斷地發掘想法、觀點、論據以及標準化嘗試。W3C 曾經設法以「Web服務活動」的名義來組織成果展,其中也包括實際作出SOAP的XML協議工做組(XML Protocol Working Group)。與Web服務有關的標準化成果(從某種程度上說與SOAP相關或者依賴於SOAP)的數量已經倍增了到了使人驚訝的程度。

  最初,SOAP是做爲XML-RPC的擴展而發展起來的,它主要強調的是,經過從WSDL文件中所得到的方法和變量名來進行遠程過程調用。現 在,經過不斷進步,人們發現了更多的使用SOAP的方式,而不只僅是採用「文件」方式——基本上是使用一個SOAP信封來傳送XML格式化文件。不管如 何,要掌握SOAP,瞭解WSDL所扮演的角色是最根本的。

SOAP數據包結構解析

SOAP的消息被稱爲一個SOAP Envelope,包括SOAP Header和SOAP Body。其中,SOAP Header能夠方便的插入各類其它消息來擴充Web Service的功能,好比Security(採用證書訪問Web Service),SOAP Body則是具體的消息正文,也就是Marshall後的信息。

SOAP調用的時候,也就是向一個URL(好比 http://api.google.com/search/beta2 )發送HTTP Post報文(根據SOAP規範,HTTP Get報文也可被支持),調用方法的名字在HTTP Request Header SOAP-Action中給出,接下來就是SOAP Envelope了。服務端接到請求,執行計算,將返回結果Marshall成XML,用HTTP返回給客戶端。

如下[是移動MISC接入]Wap1.6業務訂購數據包樣例
MISC1.6的業務訂購關係同步的請求包

Java代碼   收藏代碼
  1. <?xml version="1.0" encoding="utf-8" ?>   
  2. <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.                    xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
  4.                    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"   
  5.                    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">  
  6.   <SOAP-ENV:Header>  
  7.     <TransactionID xmlns="http://10.1.2.122/misc/dsmp.xsd">  
  8. 00110100037392</TransactionID>   
  9.   </SOAP-ENV:Header>  
  10.   <SOAP-ENV:Body>  
  11.     <SyncOrderRelationReq xmlns="http://10.1.2.122/misc/dsmp.xsd">  
  12.       <Version>1.5.0</Version>   
  13.       <MsgType>SyncOrderRelationReq</MsgType>   
  14.       <Send_Address>  
  15.         <DeviceType>0</DeviceType>   
  16.         <DeviceID>0011</DeviceID>   
  17.       </Send_Address>  
  18.       <Dest_Address>  
  19.         <DeviceType>400</DeviceType>   
  20.         <DeviceID>0</DeviceID>   
  21.       </Dest_Address>  
  22.       <FeeUser_ID>  
  23.         <UserIDType>2</UserIDType>   
  24.         <MSISDN />   
  25.         <PseudoCode>00116000000286</PseudoCode>   
  26.       </FeeUser_ID>  
  27.       <DestUser_ID>  
  28.         <UserIDType>2</UserIDType>   
  29.         <MSISDN />   
  30.         <PseudoCode>00116000000286</PseudoCode>   
  31.       </DestUser_ID>  
  32.       <LinkID>SP</LinkID>   
  33.       <ActionID>1</ActionID>   
  34.       <ActionReasonID>1</ActionReasonID>   
  35.       <SPID>919102</SPID>   
  36.       <SPServiceID>0000000064</SPServiceID>   
  37.       <AccessMode>2</AccessMode>   
  38.       <FeatureStr />   
  39.     </SyncOrderRelationReq>  
  40.   </SOAP-ENV:Body>  
  41. </SOAP-ENV:Envelope>  


MISC1.6的業務訂購關係同步的響應包:
Java代碼   收藏代碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.          xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
  4.          xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"   
  5.          xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">  
  6.   <SOAP-ENV:Header>  
  7.     <TransactionID xmlns="http://www.monternet.com/dsmp/schemas/">  
  8. 00110100037392</TransactionID>  
  9.   </SOAP-ENV:Header>  
  10.   <SOAP-ENV:Body>  
  11.     <SyncOrderRelationResp xmlns="http://www.monternet.com/dsmp/schemas/">  
  12.       <Version>1.5.0</Version>  
  13.       <MsgType>SyncOrderRelationResp</MsgType>  
  14.       <hRet>0</hRet>  
  15.     </SyncOrderRelationResp>  
  16.   </SOAP-ENV:Body>  
  17. </SOAP-ENV:Envelope>  

實戰SOAPI

如今作SOAP開發通常有三種方式選擇
    * PEAR自帶的soap擴展,
    * PHP自帶的SOAP擴展,
    * NuSOAP(純PHP,彷佛已通過時)
注:還有WSO2.org(關於WSO2.org能夠考慮嘗試一下)

PHP 5 中新增了內置的 SOAP 擴展,咱們稱之爲 ext/soap。它是做爲 PHP 的一部分提供的,所以不須要下載、安裝和管理單獨的包。這是第一個用 C 而不是 PHP 爲 PHP 編寫的 SOAP 實現,所以做者聲稱它的速度要快得多。

由於新的擴展是 PHP 的完整組成部分之一,相關文檔包含在 PHP 手冊的 Function Reference 部分(php_soap.dll)。

SOAP 參考是以一個重要的免責聲明開始的:

警告:該擴展是試驗性的(EXPERIMENTAL)。本擴展的行爲,包括關於本擴展的函數名和其餘內容,在之後的 PHP 版本中隨時可能改變,不另行通知。使用該擴展的風險自負。

警告看起來有點讓人擔憂,但實際上這個擴展彷佛獲得了很好的支持。和任何新代碼同樣,該擴展也存在缺陷,可是報告的問題一般很快就能獲得修正。在 PHP 站點上能夠看到缺陷列表。咱們估計,在未來的 PHP 版本中,該擴展將從試驗性功能轉爲主流功能

一個訪問.NET WEB服務的客戶端例子
Java代碼   收藏代碼
  1. <?php  
  2.    
  3. $objSoapClient = new SoapClient("http://www.webservicemart.com/uszip.asmx?WSDL");  
  4.    
  5. $param=array("ZipCode"=>'12209');  
  6. $out=$objSoapClient->ValidateZip($param);  
  7. $data=$out->ValidateZipResult;  
  8. echo $data;  
  9. ?>  


運行後輸出
Java代碼   收藏代碼
  1. <result code="200"><item zip="12209" state="NY"   
  2. latitude ="42.64081" longitude ="-73.7856"/></result>  


在實驗的過程中,使用了一個抓包工具Wireshark來分析報文。Wireshark很不錯,在Filter處設置ip.addr == 208.109.78.12(208.109.78.12 是 www.webservicemart.com 的IP),而後啓動監控,能夠分析上述調用過程當中HTTP包是什麼樣的。


實戰SOAPII
用PHP創建SOAP服務

創建soap_server.php(虛擬路徑爲:http://172.16.0.24/php/soap/soap_server.php)

Java代碼   收藏代碼
  1. <?php  
  2. /** 
  3. * A simple math utility class 
  4. * @author John Coggeshall john@zend.com 
  5.  */  
  6. class math {  
  7.   /** 
  8.    * Add two integers together 
  9.   * 
  10.   * @param integer $a The first integer of the addition 
  11.   * @param integer $b The second integer of the addition 
  12.   * @return integer The sum of the provided integers 
  13.    */  
  14.   public function add($a, $b) {  
  15.     return $a + $b;  
  16.   }  
  17.    
  18.  /** 
  19.   * Subtract two integers from each other 
  20.   * 
  21.   * @param integer $a The first integer of the subtraction 
  22.   * @param integer $b The second integer of the subtraction 
  23.   * @return integer The difference of the provided integers 
  24.   */  
  25.   public function sub($a, $b) {  
  26.     return $a - $b;  
  27.   }  
  28.    
  29.  /** 
  30.   * Div two integers from each other 
  31.   * 
  32.   * @param integer $a The first integer of the subtraction 
  33.   * @param integer $b The second integer of the subtraction 
  34.   * @return double The difference of the provided integers 
  35.   */  
  36.   public function div($a, $b) {  
  37.     if($b == 0) {  
  38.       throw new SoapFault(-1, "Cannot divide by zero!");  
  39.     }  
  40.     return $a / $b;  
  41.   }    
  42. }  
  43.   $server = new SoapServer('math.wsdl', array('soap_version' => SOAP_1_2));  
  44.   $server->setClass("math");  
  45.   $server->handle();  
  46.    
  47. ?>  


注意幾點:

       
  1. math類是即將公開的webservice.
  2.    
  3. 注$server→setClass,不是$server→addClass


用PHP客戶端訪問剛創建SOAP服務
Java代碼   收藏代碼
  1. <?php  
  2.   //$client = new SoapClient('http://localhost/php/soap/math.wsdl');   
  3.   $client = new SoapClient("http://localhost/php/soap/soap_server.php?WSDL");  
  4.   try {  
  5.     $result = $client->div(8, 2); // will cause a Soap Fault if divide by zero  
  6.     print "The answer is: $result";  
  7.   } catch(SoapFault $e) {  
  8.     print "Sorry an error was caught executing your request: {$e->getMessage()}";  
  9.   }  
  10. ?>  


本質上,http://localhost/php/soap /soap_server.php?WSDL就是要訪問到註釋行所指的wsdl描述文件,因此這個WSDL文件必須事先生成。而對於其餘語言如Java則 能夠動態生成。我目前的學習發現對於php自帶的SOAP擴展要求這個WSDL文件必須事先生成好。

能夠用ZendStudio生成靜態的WSDL文件,此時用到math類的phpdoc做爲生成WSDL的元數據。 用ZendStudio生成wsdl文件時,必須正確說明web服務目標地址,片段以下:
Java代碼   收藏代碼
  1. ...  
  2.     <service name="mathService">  
  3.         <port name="mathPort" binding="typens:mathBinding">  
  4.             <soap:address location="http://localhost/php/soap/soap_server.php"/>  
  5.         </port>  
  6.     </service>  
  7. ....  


特別注意:我發現調用php webserver的方法和調用.net web服務的方法不同。 調用.net service方法必須傳入命名參數;而調用php web服務方法,必定不能傳入命名參數,只能按順序傳入,爲何?這一點尤爲要注意
相關文章
相關標籤/搜索