概述(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(); ?>
注意幾點:
用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> ....