WSDL原来是这样的
在刚开始学习Webservice的时候,发现里面涉及到的知识点还真不少,每一点单拿出来都可以自成一派了。尤其是看到WSDL的时候,查了很长时间的资料,依然是有些迷惑,对其没有一个清晰的认识。随着在以后的工作中,自己写了一些WSDL的案例,才逐渐的对其内部原理有了一些认识。
首先先看一下WSDL的作用:WSDL(Web Service Description Language)用XML格式的文件来描述可用的Web服务。其实说白了就是一个标准,终端按照这个标准在网络中创建Web服务,客户端也按照此标准去连接这个服务,并且根据WSDL文件获知自己所需要的操作。
接下来我想说一下WSDL的发展过程,了解WSDL的产生历史,在以后的学习过程中不至于产生迷惑。
WSDL的第一个版本是WSDL1.0 在2000年9月有IBM,Microsoft以及Ariba开发,目的就是描述Web Service 的SOAP工具包。随后在2001年3月,WSDL 1.1版本发布,此举标志着WSDL走向了正轨。但是在1.0 和1.1之间并没有产生多大的变化。时隔两年,在2003年6月最为W3C的工作草案 WSDL1.2发布。按照W3C的说法,WSDL1.2相对于1.1版本来说开发者使用起来更简单并且更灵活了。但是WSDL1.2并不支持大多数的SOAP服务。
在2007年6月,WSDL1.2被正式更名为WSDL2.0,此时WSDL2.0也成为了W3C的推荐版本。做出这一改变的原因是2.0版本相对于1.1版本来说有了实质性的改变,所以上升了一个等级。
所以说现在WSDL流行的两个版本是WSDL2.0 和 WSDL1.1。虽说WSDL2.0 是W3C推荐的版本,但是现在大多数的厂商支持的还是WSDL1.1。举个例子来说,我们都知道PHP的一款官方IDE——zendstudio还有java IDE——Eclipse,当我们使用它们新建WSDl文件时,这个WSDl文件所遵循的格式还是WSDL1.1版本的格式。在我平时的工作中,使用的WSDL也是遵循的1.1版本的格式。
那WSDL1.1和WSDL2.0的格式究竟是怎样的呢,下面我来向大家介绍介绍。
首先我们看一下WSDL1.1,按照此标准,在WSDL文件中包含下面七项内容
1. Types
可以认为是一个容器,容器里的内容是数据类型的描述,当然需要借助于XML Schema 来达到这一目的。那么这个容器的格式如下
<wsdl:types>
<xsd:schema targetNamespace="http://www.test.com/WSDLFile/">
<xsd:element name="Operation">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OperationResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
2. Message
对操作接口进行一个抽象的定义。格式如下:
<wsdl:message name="OperationRequest">
<wsdl:part element="tns:Operation" name="parameters"/>
</wsdl:message>
<wsdl:message name="OperationResponse">
<wsdl:part element="tns:OperationResponse" name="parameters"/>
</wsdl:message>
Messages包含了一个或者多个part 元素,对于Message的属性name的值是唯一的,和当前整个WSDL文件中的人和一个Message的name值都不能相同。Part的属性name的值也是唯一的,和当前Message中的其它的任何一个part的name的值都不能相同,当然处于不同的Message中的part的name的值可以相同。
每一个part元素都关联message-type属性,这个message-type属性一般包含两部分:element和type。Message中的每一个part对应Types中的一个element元素,并且part的element属性的值为 Types中的element的name的值,前面再加上tns: ,举例如下(下面的代码是摘自 http://www.w3.org/TR/wsdl#_introduction):
<types>
<schema .... >
<element name="PO" type="tns:POType"/>
<complexType name="POType">
<all>
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<all>
<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</all>
</complexType>
</element>
</all>
</complexType>
<complexType name="Item">
<all>
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</all>
</complexType>
<element name="Invoice" type="tns:InvoiceType"/>
<complexType name="InvoiceType">
<all>
<element name="id" type="string"/>
</all>
</complexType>
</schema>
</types>
<message name="PO">
<part name="po" element="tns:PO"/>
<part name="invoice" element="tns:Invoice"/>
</message>
对于Message这一项在WSDL2.0中已经去掉了。
3. Port Type
由终端定义的一系列的抽象方法,其格式如下
<wsdl:portType name="WSDLFile">
<wsdl:operation name="Operation">
<wsdl:input message="tns:OperationRequest"/>
<wsdl:output message="tns:OperationResponse"/>
</wsdl:operation>
</wsdl:portType>
同样的,port type 的属性name的值不同于整个WSDL文档中其他的prottype的name的值。
WSDL有四种传递方式:
One-way: 终端服务接受消息
<wsdl:operation name="Operation">
<wsdl:input message="tns:OperationRequest"/>
</wsdl:operation>
Request-response:终端服务接受消息,并且发送相关的消息给客户端
<wsdl:operation name="Operation">
<wsdl:input message="tns: OperationRequest"/>
<wsdl:output message="tns:OperationResponse"/>
</wsdl:operation>
Solicit-response:终端发送一个消息,并且接受一个相关消息
<wsdl:operation name="Operation">
<wsdl:output message="tns:OperationResponse"/>
<wsdl:input message="tns: OperationRequest"/>
</wsdl:operation>
Notification:终端服务发送一个消息
<wsdl:operation name="Operation">
<wsdl:output message="tns:OperationResponse"/>
</wsdl:operation>
对于input和output的name的值来说,每一个input或者output的name的值在所有的input和output中是唯一的。当然WSDL也提供了默认的命名规则。此外对于input或者output的属性message的值为Message元素中的属性name的值,前面加上tns:
4. Binding
为porttype中的operation和message指定一个具体的传输协议(SOAP协议)和数据格式
<wsdl:binding name="WSDLFileSOAP" type="tns:WSDLFile">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Operation">
<soap:operation soapAction="http://www.test.com/WSDLFile/Operation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
同样的binding的属性name的值在所有的binding的name中是唯一的。此时binding是通过type和porttype进行绑定的,type的值为porttype的name的值在前面加上tns:。然后binding中的子元素wsdl:operation 参照 上面的operation,只是对每一个元素进行了SOAP绑定。
除了这些,在上面的示例中我们还看到有 soap:binding,soap:operation,soap:body等,这些的作用就是将soap协议绑定到接口上,因为在传输的过程中是按照soap协议传输的。
首先看soap:binding,其style的值就是operation的type属性的默认值,所以在wsdl:operation中我们可以不指定type属性。接下来是soap:operation,soapAction指定了消息请求的地址,也就是消息发送到哪个接口或者操作方法。还有就是soap:body指定了消息部分在SOAP协议中是以什么方式传输的。其中use属性是必须的,除此之外还有parts,encodingstyle和namespace属性,但是这几个不是必须的。use属性的值有两个literal和encoded,以此判断消息部分是否使用某种编码规则进行编码,或者定义一种具体的模式。
在实际应用中SOAP协议对于开发者来说是透明的,编程语言中都将SOAP协议封装成了具体的函数来供我们开发调用。如果想要详细了解SOAP协议的机制,可以参考http://www.w3.org/TR/soap12-part1/#soapbody
5. Port
定义了链接web service的地址,这个地址就是一个HTTP URL
<wsdl:service name="WSDLFile">
<wsdl:port binding="tns: WSDLFileSOAP" name="WSDLFileSOAP">
<soap:address location="http://www.test.com/"/>
</wsdl:port>
</wsdl:service>
Port的name值在所有的Port的name中是唯一的。属性binding的值为上面binding元素中的name的值前面加上tns:
这里需要注意的是一个Port只能指定一个address,并且在port中除了address不能包含其他的元素。
6. Service
可以理解为一组相关的port
<wsdl:service name="WSDLFile">
<wsdl:port binding="tns: WSDLFileSOAP" name="WSDLFileSOAP">
<soap:address location="http://www.test.com/"/>
</wsdl:port>
</wsdl:service>
同样其name值在所有的service的name中是唯一的。在一个service下面的一组port是有关系的。一、每个port之间不能相互通信;二、如果一个service中的多个port共享一个porttype,但是每个port又有不同的address和binding,那么这些port需要提供等价的行为,以便WSDL文档可以根据某个标准来选择相应的port进行通信。三、因为这些port提供的信息有一定的关联性,所以可以根据这些port了解一个service的porttype。
以上就是WSDL1.1版本的格式,在WSDL2.0中除了去掉了Message这一项外,而且还替换了port Type 为Interface。由于我在平时使用的时候,都是用的WSDL1.1,没有使用过2.0版本,所以我对此还不是很了解。待我好好研究研究2.0,之后再为大家奉上WSDL2.0的版本。当然如果大家有什么好的建议,也欢迎在下面留言,大家共同讨论,共同进步。
相关文章
使用 Docker 网络主机命令
发布时间:2023/04/18 浏览次数:111 分类:Docker
-
在本文中,我们将学习如何使用 --network 命令将容器添加到主机网络。 如果我们不使用此命令指定网络,我们还将了解如何将容器添加到默认网络。
在 Docker Compose 中添加网络模式
发布时间:2023/04/17 浏览次数:84 分类:Docker
-
默认情况下,单个网络由 Docker Compose 在我们的应用程序中创建,并将每个容器作为服务添加到那里。 网络上的每个容器都可以被单个网络上的容器访问和找到。
Flask 网络套接字
发布时间:2023/03/27 浏览次数:136 分类:Python
-
通过这个解释,我们将了解 WebSocket 是什么以及它是如何在客户端和服务器之间工作的。我们还将学习如何借助 Flask 中的 flask_socketio 模块制作一个实时聊天应用程序。
Python 网络编程简介
发布时间:2023/02/07 浏览次数:77 分类:网络
-
本教程将介绍 Python 中的套接字以及如何使用 socket 模块在 Python 中构建 HTTP 服务器和客户端。 它还将涵盖 Tornado,这是一个 Python 网络库,非常适合长轮询、WebSockets 和其他需要与每个用
linux/unix 中的十大基本网络命令
发布时间:2023/02/06 浏览次数:89 分类:网络
-
网络是 Unix 的重要组成部分,它提供了许多工具和命令来诊断任何网络问题。 我们经常需要查看会话是否已连接。 由于很多协议使用套接字,我们可以使用 Linux 中可用的 netstat 、 te
修复 NET::ERR_CERT_AUTHORITY_INVALID 错误的 9 种方法
发布时间:2021/10/13 浏览次数:8320 分类:网络
-
有时候即使在网站上安装了 SSL 证书,网站的用户也可能会遇到 `NET::ERR_CERT_AUTHORITY_INVALID` 错误。简而言之,浏览器无法识别你的证书的有效性。