你喜欢SOAP吗?反正我不喜欢!
叫什么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','struct',//这里说明是结构体 'all',//按照什么排序,有三个选择all(全部)|sequence(次序)|choice(选择) '',array( 'abc' => array('name'=>'abc','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了~! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |