zoukankan      html  css  js  c++  java
  • PHP使用SOAP做webservice

    简介

    PHP的SOAP扩展可以用来提供和使用Web services。换句话说,PHP开发者可以利用这个PHP扩展来写他们自己的Web services,也可以写一些客户端来使用给定的Web services。

    PHP5中的这个SOAP扩展目的是为了实现PHP对Web services的支持。与其它实现PHP对Web services的支持的方法不同,SOAP扩展是用C写的,因此它比其它方法具有速度优势。

    SOAP扩展支持以下规范。

    * SOAP 1.1

    * SOAP 1.2

    * WSDL 1.1

    SOAP扩展主要用来处理RPC形式的Web services。不过,你也可以使用文本形式的WSDL文件配合WSDL模式的服务端和客户端。

    这个扩展使用 GNOME XML库来处理XML。

    扩展中的类

    这个扩展实现了6个类。其中有三个高级的类,它们的方法很有用,它们是 SoapClient,SoapServer和SoapFault。另外三个类除了构造器外没有其它别的方法,这三个是低级的类,它们是SoapHeader,SoapParam和SoapVar。

    SoapClient类

    这个类用来使用Web services。SoapClient类可以作为给定Web services的客户端。

    它有两种操作形式:

    * WSDL 模式

    * Non-WSDL 模式

    在WSDL模式中,构造器可以使用WSDL文件名作为参数,并从WSDL中提取服务所使用的信息。

    non-WSDL模式中使用参数来传递要使用的信息。这个类有许多可以用来使用服务的有用的方法。其中SoapClient::__soapCall()是最重要的。这个方法可以用来调用服务中的某个操作。

    SoapServer类

    这个类可以用来提供Web services。与SoapClient类似,SoapServer也有两种操作模式:WSDL模式和non-WSDL模式。这两种模式的意义跟 SoapClient的两种模式一样。在WSDL模式中,服务实现了WSDL提供的接口;在non-WSDL模式中,参数被用来管理服务的行为。

    在SoapServer类的众多方法中,有三个方法比较重要。它们是SoapServer::setClass(),SoapServer::addFunction()和SoapServer::handle()。

    SoapServer::setClass()方法设定用来实现Web Service的类。SoapServer::setClass所设定的类中的所有公共方法将成为Web Services的操作(operation)。

    SoapServer::addFunction()方法用来添加一个或多个作为Web Services操作(operation)的函数。

    SoapServer:: handle()方法指示Web Service脚本开始处理进入的请求。Web Service脚本是用PHP脚本写的一个或多个SoapServer对象的实例。尽管你可以有不止一个的SoapServer对象,但通常的习惯是一个脚本只拥有一个SoapServer实例。在调用SoapServer::handle()方法之前,Web Service脚本会使用设置在SoapServer对象实例上的任何信息来处理进入的请求和输出的相应。

    SoapFault类

    这个类从Exception类继承而来,可以用来处理错误。SoapFault实例可以抛出或获取Soap错误的相关信息并按程序员的请求处理。

    SoapHeader类

    这个类可以用来描述SOAP headers。它只是一个只包含构造器方法的数据容器。

    SoapParam类

    SoapParam也是一个只包含构造器方法的数据容器。这个方法可以用来描述传递给Web services操作的参数。在non-WSDL模式中这是一个很有用的类,可以用来传递所期望格式的参数信息。

    SoapVar类

    SoapVar也是一个只包含构造器的低级类,与SoapHeader和SoapParam类相似。这个类可以用来给一个Web services操作传递编码参数。这个类对non-WSDL中传递类型信息是非常有用的。

    WSDL VS. non-WSDL模式

    Web Services有两种实现模式:契约先行(Contract first)模式和代码先行(Code first)模式。

    契约先行模式使用了一个用XML定义的服务接口的WSDL文件。WSDL文件定义了服务必须实现或客户端必须使用的接口。SoapServer和SoapClient的WSDL模式就基于这个概念。

    在代码先行模式中,首先要先写出实现服务的代码。然后在大多数情况下,代码会产生一个契约,换种说法,一个WSDL。接着客户端在使用服务的时候就可以使用那个WSDL来获得服务的接口。尽管如此,PHP5的扩展并没有从代码输出一个WSDL的规定,考虑到这种情况,可以在non-WSDL模式下使用 SoapServer和SoapClient。

    SOAP扩展与Hello World

    这一节介绍如何使用WSDL模式和non-WSDL模式来实现服务和客户端。相对而言,使用WSDL模式来实现服务和客户端会比较容易,假定已经有一个定义了接口的WSDL文件。因此这一节会先介绍如何使用WSDL模式实现一个Web Service。

    在这个Hello World例子的服务中有一个被命名为greet的操作。这个操作有一个字符串形式的名字并返回一个字符串形式的greeting。所用到的WSDL如下:

    PLAIN TEXT

    XML:

    1. <wsdl:definitions  

    2.     xmlns:impl='http://wso2.org/wsf/php/helloService'

    3.     xmlns:intf='http://wso2.org/wsf/php/helloService'

    4.     xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'

    5.     xmlns:wsdlsoap='http://schemas.xmlsoap.org/wsdl/soap/'

    6.     xmlns:xsd='http://www.w3.org/2001/XMLSchema'

    7.     targetNamespace='http://wso2.org/wsf/php/helloService'>

    8.   <wsdl:types>

    9.     <schema elementFormDefault='qualified'

    10.         xmlns:impl='http://wso2.org/wsf/php/helloService'

    11.         xmlns:intf='http://wso2.org/wsf/php/helloService'

    12.         xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'

    13.         xmlns="http://www.w3.org/2001/XMLSchema"

    14.         targetNamespace='http://wso2.org/wsf/php/helloService'>

    15.       <element name='greet'>

    16.         <complexType>

    17.           <sequence>

    18.             <element name='name' type='xsd:string' />

    19.           </sequence>

    20.         </complexType>

    21.       </element>

    22.       <element name='greetResponse'>

    23.         <complexType>

    24.           <sequence>

    25.             <element name='greetReturn' type='xsd:string' />

    26.           </sequence>

    27.         </complexType>

    28.       </element>

    29.     </schema>

    30.   </wsdl:types>

    31.   <wsdl:message name='greetRequest'>

    32.     <wsdl:part name='parameters' element='impl:greet' />

    33.   </wsdl:message>

    34.   <wsdl:message name='greetResponse'>

    35.     <wsdl:part name='parameters' element='impl:greetResponse' />

    36.   </wsdl:message>

    37.   <wsdl:portType name='helloService'>

    38.     <wsdl:operation name='greet'>

    39.       <wsdl:input name='greetRequest' message='impl:greetRequest' />

    40.       <wsdl:output name='greetResponse' message='impl:greetResponse' />

    41.     </wsdl:operation>

    42.   </wsdl:portType>

    43.   <wsdl:binding name='helloServiceSoapBinding' type='impl:helloService'>

    44.     <wsdlsoap:binding transport='http://schemas.xmlsoap.org/soap/http' style='document' />

    45.     <wsdl:operation name='greet'>

    46.       <wsdlsoap:operation soapAction='helloService#greet' />

    47.       <wsdl:input name='greetRequest'>

    48.         <wsdlsoap:body use='literal' />

    49.       </wsdl:input>

    50.       <wsdl:output name='greetResponse'>

    51.         <wsdlsoap:body use='literal' />

    52.       </wsdl:output>

    53.     </wsdl:operation>

    54.   </wsdl:binding>

    55.   <wsdl:service name='helloService'>

    56.     <wsdl:port binding='impl:helloServiceSoapBinding' name='helloService'>

    57.       <wsdlsoap:address location='http://localhost/hello/hello_service_wsdl.php' />

    58.     </wsdl:port>

    59.   </wsdl:service>

    60. </wsdl:definitions>

     

    WSDL模式服务

    下面是WSDL模式的服务所使用的SOAP扩展API代码:

    PLAIN TEXT

    PHP:

    1. <?php

    2. function greet($param) {

    3.     $retval = 'Hello '.$param->name;

    4.     $result = array('greetReturn' => $retval);

    5.     return $result;

    6. }

    7.  

    8. $server = new SoapServer('hello.wsdl');

    9. $server->addFunction('greet');

    10. $server->handle();

    11. ?>

     

    在这个服务的实现过程中,函数实现了WSDL所定义的服务操作greet,greet操作有一个WSDL指定的参数,按照greet操作的语义,这个参数是一个用户的名字。最后handle调用了触发处理请求的服务对象。

    WSDL模式客户端

    客户端代码如下

    PLAIN TEXT

    PHP:

    1. <?php

    2.  

    3. try {

    4.     $client = new SoapClient('hello.wsdl');

    5.     $result =  $client->__soapCall('greet', array(array('name' => 'Sam')));

    6.     printf("Result = %s\n", $result->greetReturn);

    7.  

    8. } catch (Exception $e) {

    9.     printf("Message = %s\n",$e->__toString());

    10. }

    11. ?>

     

    客户端代码中,首先创建一个使用WSDL文件作参数的SoapClient实例。接着__soapCall()调用作为参数传入它的操作,也就是greet和传入操作的参数。

    请求和响应

    当你将上述的PHP脚本放在你web服务器目录下的文档中,并利用WEB浏览器或在PHP解析器的命令行调用脚本,客户端发送一个SOAP请求到服务端脚本,服务端将向客户端发送一个SOAP响应来响应客户端的请求。

    下面是客户端所发送的SOAP请求:

    PLAIN TEXT

    XML:

    1. <?xml version="1.0" encoding="UTF-8"?> 

    2. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"                   

    3.                                   xmlns:ns1="http://wso2.org/wsf/php/helloService">

    4.  

    5.     <SOAP-ENV:Body>

    6.         <ns1:greet>

    7.             <ns1:name>Sam</ns1:name>

    8.         </ns1:greet>

    9.     </SOAP-ENV:Body>

    10. </SOAP-ENV:Envelope>

    下面是服务端响应上诉请求而发送的SOAP响应:

    PLAIN TEXT

    XML:

    1. <?xml version="1.0" encoding="UTF-8"?>

    2.    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

    3.                       xmlns:ns1="http://wso2.org/wsf/php/helloService">

    4.       <SOAP-ENV:Body>

    5.          <ns1:greetResponse>

    6.             <ns1:greetReturn>Hello Sam</ns1:greetReturn>

    7.          </ns1:greetResponse>

    8.       </SOAP-ENV:Body>

    9.    </SOAP-ENV:Envelope>

    上面的SOAP消息都是利用WSDL模式的服务端和客户端来获取的。也可以利用non-WSDL模式的服务端和客户端来产生与上面相同的SOAP消息。但是,PHP代码必须有一点改变。下一节会说明如何使用non-WSDL模式。

    non-WSDL模式服务端

    PLAIN TEXT

    PHP:

    1. <?php

    2. function greet($param) {

    3.     $retval = 'Hello '.$param;

    4.     return new SoapParam($retval, 'greetReturn');

    5. }

    6. $server = new SoapServer(null, array('uri' => 'http://wso2.org/wsf/php/helloService'));

    7. $server->addFunction('greet');

    8. $server->handle();

    9. ?>

     

    在non -WSDL模式中,想WSDL模式一样首先实现greet函数的功能,但是函数实现的方式跟WSDL模式稍稍有所不同。在non-WSDL模式中,我们必须返回一个SoapParam对象作为响应,而不是一个数组。创建服务时,第一个参数设为null,说明没有提供WSDL;接着传递一个选项作为参数,这个选项参数是服务的URI。最后像WSDL模式一样调用剩下的方法。

    non-WSDL模式客户端

    PLAIN TEXT

    PHP:

    1. <?php

    2. try {   

    3.     $client = new SoapClient(null,

    4.     array('location' => 'http://localhost/hello/hello_service_nonwsdl.php',

    5.     'uri' => 'http://wso2.org/wsf/php/helloService'));

    6.     $result = $client->__soapCall('greet', array(new SoapParam('Sam', 'name'))); printf("Result = %s\n", $result);

    7. } catch (Exception $e) {

    8.     printf("Message = %s\n",$e->__toString());

    9. }

    10. ?>

     

    在non-WShDL模式中,因为p没有使用WSDL,传递了一个包含服务所在位置和服务URI的参数数组作为参数。然后象WSDL模式中一样调用__soapCall()方法,但是使用了SoapParam类用指定格式打包参数。返回的结果将获取greet中的响应。

    结论

    这篇文章介绍了SOAP扩展,可以在PHP中通过它来提供和使用Web Services。PHP扩展的强项是它的简单和快速。使用C写的SOAP扩展来运行服务端和客户端是非常简单的。虽然SOAP扩展在处理一些简单的 Web Services时很有用,但是当用它来处理所有的Web Services时就表现出它的局限性。 WSO WSF/PHP就是为了弥补PHP扩展的缺陷而开发的,它是开源的,可以实现SOAP类似的功能并且支持MTOM,WS-Addressing,WS- Security和WS-RelaiableMessaging。WSO2 WSF/PHP 支持与SOAP扩展类似的API。我们正计划将API打包起来提供跟SOAP扩展一样的API,会用C来写。

  • 相关阅读:
    常用安卓开发技巧汇总
    安卓开发30:AsyncTask的用法
    JBoss AS7 快速配置
    抓包 把笔记本改造成无线路由器 —— 手机抓包牛刀小试
    Android系统手机端抓包方法
    ApkTool反编译apk,去除广告或者汉化后重新打包apk,并签名
    Android中如何像 360 一样优雅的杀死后台Service而不启动
    android service 的各种用法(IPC、AIDL)
    Android shell 下 busybox,clear,tcpdump、、众多命令的移植
    Servlet3.0中Servlet的使用
  • 原文地址:https://www.cnblogs.com/cnsanshao/p/2176368.html
Copyright © 2011-2022 走看看