WebService 服务开发
开发 WebService 服务首先需要根据接口的要求编写相关的 wsdl 文件。编写 wsdl 文件需要先对 XML 语法、XML Schema 语法以及 SOAP 语法有一些简单了解。
假设需要提供一个 Student 服务,该服务仅提供一个操作:add($student),通过 add 方法添加学生信息。即需要定义一个 Student 类,该类仅包括一个方法 add,该方法的参数是一个一维数组,数组键名包括:name(string)/sex(int)/age(int)。现在开始定义对应的 wsdl 文件。
wsdl 文件基本结构
wsdl 文件的结构大致如下:
<definitions>
<types>
definition of types........
</types> <message>
definition of a message....
</message> <portType>
<operation>
definition of a operation.......
</operation>
</portType> <binding>
definition of a binding....
</binding> <service>
definition of a service....
</service>
</definitions>
主要有五个元素构成:types、message、portType、binding、service。根元素是 definitions。
第一步:声明 wsdl 文件
<?xml version="1.0" encoding="UTF-8"?>
第二步:定义 definitions 根元素
<wsdl:definitions
name="StudentService"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example.com/student/index.php"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/student/index.php"
>
...
</wsdl:definitions>
xmlns:soap、xmlns:wsdl、xmlns:xsd 这三个命名空间是默认的命名空间,其他默认的命名空间还有:
- targetNamesapce:指定该服务所属的命名空间,作用相当于 Java 中的 package。防止与其他 wsdl 文件冲突。一般指定为服务地址即可。
- xmlns:soap:定义 soap 命名空间,指定该服务遵守的 soap 版本。
- xmlns:wsdl:定义 wsdl 命名空间。该服务遵守的 wsdl 规范。注意:如果不定义该命名空间,则需要定义一个默认命名空间,即xmlns="http://schemas.xmlsoap.org/wsdl/"。定义该命名空间后,所有的 wsdl 元素都需要加载 wsdl 前缀。
- xmlns:xsd:定义 xsd 命名空间。XML Schema 实例遵守的规范。
- xmlns:tns:自定义命名空间。tns 即 targetNamespace,该文件中定义的新元素属于该命名空间。一般定义为服务地址即可。
第三步:定义 types 元素
<wsdl:types>
<!--xsd:schema元素的targetNamespace属性必需,且值与definitions元素的xmlns:tns相同-->
<xsd:schema
targetNamespace="http://example.com/student/index.php">
<!--定义addRequest数据类型,属于tns命名空间-->
<xsd:element name="addRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0" />
<xsd:element name="sex" type="xsd:string" minOccurs="0" />
<xsd:element name="age" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!--定义addResponse数据类型,属于tns命名空间-->
<xsd:element name="addResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="msg" type="xsd:string" minOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<xsd:schema>元素中必须指定 targetNamespace 属性,值与definitions元素的xmlns:tns属性值相同。表示定义的新元素的隶属命名空间。
第四步:定义 message 元素
- <part name="fristParam" type="xsd:string" />:描述基本类型的参数。
- <part name="secondParam" element="tns:addRequest" />:描述复杂类型的参数。
<!--input message:addRequest message,隶属命名空间tns,数据类型是XML Schema中定义的addRequest-->
<wsdl:message name="addRequest">
<wsdl:part element="tns:addRequest" name="request" />
</wsdl:message>
<!--output message:addResponse message,隶属命名空间tns,数据类型是XML Schema中定义的addResponse-->
<wsdl:message name="addResponse">
<wsdl:part element="tns:addResponse" name="response" />
</wsdl:message>
第五步:定义 portType 元素
- 一个 portType 元素有一个或多个 operation 元素构成。
- 一个 operation 元素表示一个 WebService 服务,通过 operation 元素的 name 属性定义对应的 WebService 服务操作。
- 一个 operation 元素通常包括一个 input 元素 和一个 output 元素。
<!--name属性定义portType-->
<wsdl:portType name="StudentService">
<!--该operation元素对应add服务-->
<wsdl:operation name="add">
<!--input的消息类型是tns:addRequest-->
<wsdl:input name="addInput" message="tns:addRequest" />
<!--output的消息类型是tns:addResponse-->
<wsdl:output name="addOutput" message="tns:addResponse" />
</wsdl:operation>
</wsdl:portType>
第六步:定义 binding 元素
- soap:binding:包括 style 属性和 transport 属性。style 属性定义了 soap 消息格式的整体样式,值为 rpc 或 document。这两个值仅表示两种不同的将 WSDL binding 转换为 SOAP message 的方式,选择任一种即可。transport 属性指定传输协议,值为http://schemas.xmlsoap.org/soap/http,表示通过soap HTTP 方式传输;值为http://schemas.xmlsoap.org/soap/smtp,表示通过 SOAP SMTP方式传输。
- soap:operation:将指定的 WebService 服务绑定到指定的 SOAP 实现。属性 soapAction 指定 soapAction HTTP header 内容以标识对应的服务。
- soap:body:包括 use 属性,值为 encoded 和 literal。指定 input 和 output 的 message 细节。
注意:这四种组合的具体差别参考:https://www.ibm.com/developerworks/library/ws-whichwsdl/
根据服务示例定义 binding 元素:
<wsdl:binding name="StudentServiceBinding" type="tns:StudentService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="add">
<soap:operation soapAction="http://example.com/student/index.php#add" />
<wsdl:input name="addInput">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="addOutput">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
第七步:定义 service 元素
<wsdl:service name="StudentService">
<wsdl:port name="StudentServicePort" binding="tns:StudentServiceBinding">
<soap:address location="http://example.com/student/index.php?wsdl" />
</wsdl:port>
</wsdl:service>
编写结束后将文件保存为 student.wsdl。
开发服务端
class Student
{
public function add($student)
{
return [ 'msg'=>json_encode($studentList, JSON_UNESCAPED_UNICODE)];
}
}
定义 index.php:
require './Student.php';
if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST')
{
try
{
$wsdl = './student.wsdl';
$soap = new SoapServer($wsdl);
$soap->setClass('Student');
$soap->handle();
}catch (SoapFault $fault){
echo $fault->getMessage();
}
}elseif(isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['QUERY_STRING']) == 'wsdl' && $_SERVER['REQUEST_METHOD'] == 'GET')
{
header('Content-type: text/xml; charset=utf-8');
$wsdl = file_get_contents('./student.wsdl');
echo $wsdl;
}else
{
echo 'No wsdl xml file';
}
客户端调用
try
{
$soap = new SoapClient('http://127.0.0.1:8091/exercise/soap/index.php?wsdl', ['trace'=>true, 'cache_wsdl'=>WSDL_CACHE_NONE]);
$studentInfo = ['name' => 'a', 'sex'=>'0', 'age'=>'20'];
$backlog = $soap->add($studentInfo);
var_dump($backlog);
}catch(Exception $e)
{
var_dump($e->getMessage());
}
不同类型传参时的 message 元素定义
示例一:请求参数和响应数据都是基本类型
public function($int1, $str1)
{
return json_encode(func_get_args());
}
<wsdl:message name="addRequest">
<wsdl:part name="int1" type="xsd:int" />
<wsdl:part name="str1" type="xsd:string" />
</wsdl:message>
<wsdl:message name="addResponse">
<wsdl:part name="return" type="xsd:string" />
</wsdl:message>
$soap = new SoapClient('http://192.168.12.118:8091/exercise/soap/index.php?wsdl', ['trace'=>true, 'cache_wsdl'=>WSDL_CACHE_NONE]);
$backlog = $soap->add(20, 'age');
var_dump($backlog);
示例二:请求参数是长度不定的一维数组
public function($idList)
{
return json_encode($idList);
}
<wsdl:types>
<xsd:schema
targetNamespace="http://example.com/student/index.php">
<!--定义addRequest数据类型,属于tns命名空间-->
<xsd:element name="addRequest">
<xsd:complexType>
<xsd:sequence>
<!--maxOccurs="unbounded"属性表示该元素出现的最大次数不定,通过该属性定义一个长度不定的数组-->
<xsd:element name="id" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
message 元素定义:
<wsdl:message name="addRequest">
<wsdl:part name="idList" element="tns:addRequest" />
</wsdl:message>
<wsdl:message name="addResponse">
<wsdl:part name="return" type="xsd:string" />
</wsdl:message>
客户端调用:
$soap = new SoapClient('http://192.168.12.118:8091/exercise/soap/index.php?wsdl', ['trace'=>true, 'cache_wsdl'=>WSDL_CACHE_NONE]);
$backlog = $soap->add([1,2,3]);
$std = new stdClass();
$std->id = [1, 2, 3];
$backlog = $soap->add($std);
此时服务端接收到的数据格式与之前的相同。
客户端调用:
$backlog = $soap->add([1]);
服务端接口数据为:["id":"1"]。
示例三:传入多维数组
[
"num": "传入的学生信息数量",
"studentList": [
["name":1, "age":20, "sex": 0],
["name":2, "age":20, "sex": 0],
...
]
]
服务端方法:
public function($studentInfo)
{
return json_encode($studentInfo);
}
types 元素和 message 元素的定义:
<wsdl:types>
<xsd:schema
targetNamespace="http://example.com/student/index.php">
<xsd:element name="addRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="num" type="xsd:int" />
<xsd:element name="studentList" type="tns:studentList" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!--定义studentList数据结构,长度不定的数组-->
<xsd:complexType name="studentList">
<xsd:sequence>
<xsd:element name="student" type="tns:student" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<!--定义student数据结构-->
<xsd:complexType name="student">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0" />
<xsd:element name="age" type="xsd:string" minOccurs="0" />
<xsd:element name="sex" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types> <wsdl:message name="addRequest">
<wsdl:part name="studentInfo" element="tns:addRequest" />
</wsdl:message>
<wsdl:message name="addResponse">
<wsdl:part name="return" type="xsd:string" />
</wsdl:message>
定 add 方法接受一个参数,该参数是一个多为数组,结构如下:
客户端调用:
$soap = new SoapClient('http://192.168.12.118:8091/exercise/soap/index.php?wsdl', ['trace'=>true, 'cache_wsdl'=>WSDL_CACHE_NONE]);
$studentInfo = ['name' => 'a', 'sex'=>'0', 'age'=>'20'];
$list = [
'num' => 2,
'studentList' => [$studentInfo, $studentInfo],
];
$backlog = $soap->add($list);
注意:传入请求参数时,务必保持参数的传入顺序和 input message 中的 part 元素顺序一致。
WebService 服务开发的更多相关文章
- ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器
ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!! ...
- 基于CXF框架下的SOAP Webservice服务端接口开发
最近对webservice 进行入门学习,网上也是找了很多的学习资料.总得感觉就是这了解点,那了解点.感觉不够系统,不够容易入门.差不多断断续续看了一个星期了,今天小有成果,把客户端,服务端都搞定了. ...
- Spring Boot 开发 WebService 服务
WebService 虽然现在大部分互联网企业不太提倡使用,但在以第三方接口为主导的市场,对方来什么接口你还得用什么接口,不可能把接口重写了.例如大部分传统的大型企业都在用 WebService,并且 ...
- C#开发WEBService服务 C++开发客户端调用WEBService服务
编写WEBService服务端应用程序并部署 http://blog.csdn.net/u011835515/article/details/47615425 编写调用WEBService的C++客户 ...
- Java创建WebService服务及客户端实现(转)
简介 WebService是一种服务的提供方式,通过WebService,不同应用间相互间调用变的很方便,网络上有很多常用的WebService服务,如:http://developer.51cto. ...
- CXF发布webService服务以及客户端调用
这篇随笔内容是CXF发布webService服务以及客户端调用的方法 CXF是什么? 开发工作之前需要下载CXF和安装 下载地址:http://cxf.apache.org 安装过程: <1&g ...
- Node.js 使用 soap 模块请求 WebService 服务接口
项目开发中需要请求webservice服务,前端主要使用node.js 作为运行环境,因此可以使用soap进行请求. 使用SOAP请求webservice服务的流程如下: 1.进入项目目录,安装 so ...
- Vmware Vsphere WebService SDK开发(第一讲)-基本知识学习
刚开始这方面开发的时候,不知道如何下手,能够查到的资料特别少,而且看到很多网友和我一样也在找这方面的资料.接下来的一段时间我就结合自己所参与的项目,完成关于Vmware Vsphere WebServ ...
- 二十、【.Net开源】EFW框架核心类库之WebService服务
回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baid ...
随机推荐
- BZOJ_3476_[Usaco2014 Mar]The Lazy Cow_扫描线+切比雪夫距离
BZOJ_3476_[Usaco2014 Mar]The Lazy Cow_扫描线+切比雪夫距离 Description It's a hot summer day, and Bessie the c ...
- Python 函数定义以及参数传递
Python 函数定义以及参数传递1.函数定义#形如def func(args...): doSomething123以关键字def 开头,后面是函数名和参数下面是函数处理过程. 举例: def ad ...
- CentOS6.0忘记root密码解决办法
说明操作系统:CentOS 6.0遇到问题:忘记管理员账号root的密码,进不了系统解决办法:重置root密码为123456操作: 开机启动系统,在进入系统之前按键盘上面的Esc键,会进入下面的界面 ...
- [转]RF+Selenium2Library元素定位不到的问题
原文地址:http://m.blog.csdn.net/m0_37553368/article/details/78016729 在基于RobotFramework框架使用Selenium2Libra ...
- 用UNIX的cat命令用于给文本加行号 (转载)
转载:http://blog.csdn.net/vicant/article/details/2317721 有时候需要给文本加上行号,用UNIX的cat命令可以进行这项工作. cat命令的用法如下: ...
- bzoj 1951: [Sdoi2010]古代猪文 【中国剩余定理+欧拉定理+组合数学+卢卡斯定理】
首先化简,题目要求的是 \[ G^{\sum_{i|n}C_{n}^{i}}\%p \] 对于乘方形式快速幂就行了,因为p是质数,所以可以用欧拉定理 \[ G^{\sum_{i|n}C_{n}^{i} ...
- A+B Problem——经典中的经典
A+B Problem,这道题,吸收了天地的精华,是当之无愧的经典中的经典中的经典.自古以来OIer都会经过它的历练(这不是白说吗?),下面就有我herobrine来讲讲这道题的各种做法. 好吧,同志 ...
- Java 反射机制详解(上)
一.什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java ...
- c语言中的rand()函数用法
rand() rand()函数作用:用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的. rand()函数返回:返回一个范围在 ...
- Python测试工具——nose
1.nose 特点: a) 自动发现测试用例(包含[Tt]est文件以及文件包中包含test的函数) b) 以test开头的文件 c) 以test开头的 ...