你喜歡SOAP嗎?反正我不喜歡!

來源:互聯網
上載者:User

叫什麼Simple Object Access Protocol,實際上一點都不Simple!

說什麼輕量級協議,從它基於XML的編碼就知道它有多臃腫!

說什麼跨平台特性,其實各個語言需要自己實現一整套SOAP!

除了給人看的介面文檔外,還需要一份給機器看的wsdl,並且介面調用前要先載入它!

有人也許會說“wsdl是基於xml的,人也可以直接閱讀啊,完全可以不需要介面文檔!”

。。。那你說說你有幾個項目是這麼乾的?尤其是外部合作的項目!

…………

唯一的好處就是調用者可以像本地一樣調用遠程函數,但這建立在複雜封裝的基礎上,一切都要標準協議,一定程度上意味著悲催的可控性和靈活性。

總之這種感覺就像從linux的開源天堂突然掉入MS的世界……

好吧,可能是我常年用PHP養成的土鱉習慣吧,高端的東西還真享受不了~

(我靠。。。誰拿拖鞋丟我?!)

---------------------------------------- 我是分割線 --------------------------------------------

吐槽完了,下面就說說這兩天用PHP使用SOAP的感受吧~

其實PHP內建有soap擴充,但是。。。這是個略顯坑爹的擴充。

SoapServer端沒帶產生wsdl的功能,需要使用工具(如Zend)或。。。手寫 - -|||

雖然SoapClient端支援無wsdl的方式調用,但是。。。沒有wsdl你打算給誰用?難不成自娛自樂麼~

so,最後我還是用了第三方的包,沒錯,就是nusoap!

用它實現Server端,動態產生標準的wsdl地址;用戶端倒是可以使用內建的soap擴充。

網上有一些簡單的樣本,不是過於簡單,就是不完整,總之一些關鍵點經常沒有提到,遇到的很多問題最後還是通過翻源碼解決的。

完整的例子就不寫了,這裡僅對值得特別注意的地方做下mark(其他基礎知識和簡單範例請先自行google):

1、調用addComplexType建立複合類型

常用的有兩種,一種是array類型(對應php裡的索引數組),可以這麼註冊:

$server->wsdl->addComplexType(    'testParam', //複合參數名    'complexType',    'array', //這裡說明是數組    '',     '', //基本約束     array(), //xsd:element    array(        'abc' => array('name'=>'abc', 'type'=>'xsd:string'),        'def' => array('name'=>'def', 'type'=>'xsd:int')        ) //xsd:attribute     );

例如請求參數為該類型,則Client端可以這麼調用:

//複合參數:testParam//參數一:abc=linvo//參數二:def=123$ret = $client->myFun(array('linvo', '123')); 

Server端可以這麼接收參數:

function myFun($testParam){    $param1 = $testParam[0];    $param2 = $testParam[1];    return array($param1, $param2); //假設響應參數也為該類型}

還有一種是struct類型(對應php裡的雜湊數組),可以這麼註冊:

$server->wsdl->addComplexType(    'testParam', //複合參數名    'complexType',    'struct', //這裡說明是結構體    'all', //按照什麼排序,有三個選擇all(全部)|sequence(次序)|choice(選擇)    '',     array(        'abc' => array('name'=>'abc', 'type'=>'xsd:string'),        'def' => array('name'=>'def', 'type'=>'xsd:int')        ) //xsd:element     );

例如請求參數為該類型,則Client端可以這麼調用:

//複合參數:testParam//參數一:abc=linvo//參數二:def=123$ret = $client->myFun(array('abc'=>'linvo', 'def'=>'123')); 

Server端可以這麼接收參數:

function myFun($testParam){    $param1 = $testParam['abc'];    $param2 = $testParam['def'];    return array('abc'=>$param1, 'def'=>$param2); //假設響應參數也為該類型}

注意:

無論哪種形式,均不用體現複合參數名,只是struct形式的複合參數中的二級參數需要體現參數名。這裡如果搞錯的話Client端可能會取到NULL。

當struct形式時,Client取到的結果為Object,如果想變為數組可以強制轉換成數組。

2、中文問題

字元集問題不管在哪裡,都讓人煩躁&%¥!

如果你和我一樣使用的是UTF-8,那麼建立soap_server對象後,需要設定這兩處的字元集:

$this->server->soap_defencoding = 'UTF-8';$this->server->xml_encoding = 'UTF-8';

現在Clinet端接收到的響應正常了,可是傳入Server端函數中的請求參數還是有問題!

通過調試發現Server擷取到的原始請求資料($data=file_get_contents("php://input");)是正常的,只是經過soap處理($server->service($data))傳入介面函數中就不對了,看了問題出在nusoap中。

翻源碼一步步跟,看到nusoap貌似只支援三種字元集 ISO-8859-1|US-ASCII|UTF-8,還好我使用的是UTF-8

而且它內部預設是轉成ISO-8859-1處理的!

在nusoap_parser類的nusoap_parser函數的第4個參數(我下載的版本:$Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $,在6577行)是

@param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1

這個值預設是true,而且應該是從server對象傳來的,那我把 $this->server->decode_utf8 = false; 後發現報錯了貌似。。。看來這個參數不僅僅影響nusoap_parser

後來索性只把nusoap_parser處的設定為false:

6582行:$this->decode_utf8 = false;

終於OK了~!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.