让我们来看一个示例WSDL文件的结构及工作原理。请注意这只是一个十分简单的WSDL文档实例。我们的目的只是简单展示下最显著的特征,后面的章节有对其详细的讨论。

<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="FooSample" targetNamespace="http://tempuri.org/wsdl/" xmlns:wsdlns="http://tempuri.org/wsdl/" xmlns:typens="http://tempuri.org/xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension" xmlns="http://schemas.xmlsoap.org/wsdl/">
<types><schema targetNamespace="http://tempuri.org/xsd" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" elementFormDefault="qualified" ></schema>
</types>
<message name="Simple.foo"><part name="arg" type="xsd:int"/>
</message>
<message name="Simple.fooResponse"><part name="result" type="xsd:int"/>
</message>
<portType name="SimplePortType"><operation name="foo" parameterOrder="arg" ><input message="wsdlns:Simple.foo"/> <output message="wsdlns:Simple.fooResponse"/></operation>
</portType>
<binding name="SimpleBinding" type="wsdlns:SimplePortType"><stk:binding preferredEncoding="UTF-8" /><soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="foo"><soap:operation soapAction="http://tempuri.org/action/Simple.foo"/><input><soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input><output><soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></output></operation>
</binding>
<service name="FOOSAMPLEService"><port name="SimplePort" binding="wsdlns:SimpleBinding"><soap:address location="http://carlos:8080/FooSample/FooSample.asp"/> </port>
</service>
</definitions>

下面只是对该WSDL文档的预览:

第一行定义了该文档是一份XML文档。尽管这一行不是必需的,但这一行有助于XML解析器对WSDL文档进行解析。

第二行定义了WSDL文档的根元素:<definitions>并有一些命名空间属性定义在根元素内,就与<types>的子元素<schema>类似。

<types>元素组成了类型段。当没有数据类型要定义时,该段可能被忽略。在示例WSDL中,该段中没有特定于应用程序的数据类型定义,但还是使用了类型段,只是用于定义在该文档中使用的schema命名空间。

<message>元素组成消息段。如果你将一个操作比作函数,那么<message>元素则定义了函数的所有参数。每个<message>的<part>子元素与参数相对应。输入参数在独立的<message>元素中定义,与输出参数隔离,输出参数定义在自己的<message>元素中。输出参数<message>元素的name属性以“Response”结尾,用于与输入参数进行区分。每一个<part>元素都有name和type属性,就像函数的参数具有类型和名称类似。<part>元素的type属性值可以是XSD基本类型,SOAP定义的类型,WSDL定义的类型或类型段定义的类型。

在PortTypes段中可以定义零个,1个或多个<portType>元素。可以不包含该段的原因是该段可以定义在独立的WSDL文档中。示例中只包含了一个<portType>元素。<portType>元素可以通过<operation>子元素定义一个或多个操作。示例只包含一个<operation>元素,名称为“foo”。这个名称就相当于函数名。<operation>元素可以包含一个,两个或三个子元素:<input>,<output>,<fault>,这三个子元素中的message属性值与消息段中的<message>元素相对应。示例中的整个<portType>元素就相当于C语言中int foo(int arg);函数的定义。

在Binding段中可以定义零个,1个或多个<binding>元素。它的功能是指定每个<operation>请求和响应如何通过网络传输。

在Services段中可以定义零个,1个或多个<service>元素。<service>元素包含<port>子元素并与Binding段中的<binding>元素相对应。

命名空间

根元素<definitions>和子元素<schema>都有namespace属性。

每个namespace属性定义了每个应用在文档中namespace的缩写。例如:“xmlns:xsd”为http://www.w3.org/2001/XMLSchema命名空间定义了xsd缩写。定义后就可以在以后的文档中使用缩写来代表完整的命名空间。

什么是命名空间?命名空间的使用是为了避免名字冲突。如果我创建了一个web Service并在WSDL文件中包括了一个name属性为foo的元素。你准备将这个服务与另一个服务一起使用,如果没有命名空间,则另一个服务中就不能在其WSDL文件中包括“foo”名称。每个服务能使用相同的名字只有当这些名字在相同的实例中表示同一个意思。使用不同的命名空间,我自己的服务中“foo”名字可以与另一个服务中相同的名字表示不同的意思。

属性targetNamespace定义了一个命名空间,所有在元素中的名称都属于这个命名空间。在示例文件中,根元素<definitions>的targetNamespace属性定义为http://tempuri.org/wsdl/。即所有定义在该文档中的名称都属于这个命名空间。<schema>元素有自己的targetNamespace属性,值为http://tempuri.org/xsd,所有定义在<schema>元素中的名字都属于这个命名空间而非上层的命名空间。

<schema>元素的下一行中定义了缺省的命名空间(xmlns="http://www.w3.org/2001/XMLSchema"),所有未经限定的名称都属于这个命名空间。

SOAP消息

一种查看WSDL文件的方法:客户端和服务器端使用该文件,该文件决定了网络上传输的数据内容。尽管SOAP使用底层的IP或HTTP协议,但应用程序决定了高层在客户和服务器端所使用的协议。换句话说,给定一个操作叫“echoInt”,执行简单的返回输入的整型操作,参数的数量,每个参数的类型以及参数在网络中如何传输(serialization)组成了应用程序规定的协议。这样的协议可以由多种方式进行指定,但我相信最好的方法是使用WSDL。如果我们通过这种方法重新审视WSDL,则其不仅是“接口契约”,而且还是一个协议定义语言。

WSDL可以定义SOAP消息是否遵循rpc或document格式。一个rpc-style消息,像示例文件中定义的,就像一个带有零个或多个参数的函数调用。一个document-style消息则更平面化且只需要少量的嵌套层次。下面的XML消息是使用SoapClient object in MS SOAP Toolkit 2.0对同一个WSDL文件解析后发送和接收的结果。

从客户端发起一个函数调用“foo(5131953)”:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><m:foo xmlns:m="http://tempuri.org/message/"><arg>5131953</arg> </m:foo></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

从服务器端接到响应:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body> <SOAPSDK1:fooResponse xmlns:SOAPSDK1="http://tempuri.org/message/"><result>5131953</result></SOAPSDK1:fooResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

函数调用的消息及其返回的消息都是有效的XML。一个SOAP消息包括一个<Envelope>元素,该元素包括可选的<Header>元素及最少一个<Body>元素。发送和接收消息在<Envelope>元素都有单个的<Body>元素。rpc功能调用消息体有一个“foo”操作名,同时返回消息体中包括了“fooResponse”元素。foo元素只有一个子元素<arg>,它代表单个参数,在示例WSDL文件中描述。同样fooResponse元素也有一个<result>子元素。

XML Schema在WSDL类型和消息段

WSDL的数据类型是基于“XML Schema:Datatypes”(XSD)也是W3C所推荐的。XSD文档有三个不同的版本(1999, 2000/10, and 2001),将其申明在<definitions>元素的一个nameSpace属性中,指定在特殊WSDL文件中所使用的版本。

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

Prefix Equivalent Namespace Description
soapenc http://schemas.xmlsoap.org/soap/encoding SOAP 1.1 enc
wsdl http://schemas.xmlsoap.org/wsdl/soap WSDL 1.1
xsd http://www.w3.org/2001/XMLSchema XML Schema

XSD定义了两类内建类型:基本和继承,具体的参见:http://www.w3.org/TR/2001/PR-xmlschema-2-20010330

复杂类型

XML Schema允许定义复杂类型,在C语言中则用struct来表示。例如,定义下面C struct:

typedef struct { string firstName; string lastName; long ageInYears; float weightInLbs; float heightInInches;
} PERSON;

使用XML Schema来表示:

<xsd:complexType name="PERSON"> <xsd:sequence><xsd:element name="firstName" type="xsd:string"/><xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/></xsd:sequence>
</xsd:complexType>

但是<complexType>能够表达C struct所不能表达的功能。除了<sequence>子元素还允许其它的子元素。可以使用<all>子元素来代替<sequence>:

<xsd:complexType name="PERSON"> <xsd:all><xsd:element name="firstName" type="xsd:string"/><xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/></xsd:all>
</xsd:complexType>

当<all>子元素出现时,表示其内部的子元素可以以任意的顺序出现且每个子元素都是可选的。这就不太像C struct了。

<portType>和<operation>元素

一个portType定义了若干个operation。在portType中的operation元素定义了该portType中所有方法调用的语法。每一个operation元素定义了方法名,参数(使用<message>元素)以及每个参数的类型(<message>中定义的<part>元素)。

一个WSDL文档中可以有多个<portType>元素。每组<portType>包含了一组相关的操作。

在<operation>元素中,只能出现一个<input>,一个<output>,一个<fault>元素,每个元素都有name和message属性。

<input>,<output>,<fault>三个元素的name属性有何作用呢?它的作用是用来对相同操作名进行区分(重载)。

<binding>和<operation>元素

Binding段是用来对传输中的协议,序列化和编码进行全面的定义。因此,Types,Message和Port Type段用来处理抽像的数据内容,Binding段则用来定义传输过程中物理细节。

将binding规范从数据及消息中分离表示服务提供者们如果使用相同的业务类型可以将其标准化到一组操作中(portType)。每一个提供者可以根据自己的要求对binding进行定制。这就有助于将抽像的定义(types, message, portType)从WSDL文档中分离出并定义到独立的文档中,所有的业务规则相同的服务提供者使用相同的抽像定义,而对binding进行定制。例如:银行可以定义一组标准的银行操作并定义到一个抽像的WSDL文档中,而各个银行可以对使用协议,序列化和编码进行定制。

从示例中提取的binding段:

<binding name="SimpleBinding" type="wsdlns:SimplePortType"><stk:binding preferredEncoding="UTF-8" /><soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="foo"><soap:operation soapAction="http://tempuri.org/action/foo1"/> <input name="foo1"><soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input></operation><operation name="foo"><soap:operation soapAction="http://tempuri.org/action/foo2"/> <input name="foo2"><soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input></operation>
</binding>

<binding>元素有一个name属性(示例中值为“SimpleBinding”),定义这个name是为了在Services段的<port>元素中对其进行引用。type属性则是对<portType>元素的引用。第二行是MSTK2的扩展元素,<stk:binding>,指定了优先使用的编码类型为UTF-8。

<soap:binding>元素指定了消息格式(rpc)和transport方式。transport属性引用一个namespace指定使用HTTP SOAP协议。

有两个<operation>元素具有相同的名字“foo”,通过<input>元素的name属性进行区分,分别为“foo1”和“foo2”。在<operation>元素中的<soap:operation>元素都包括“soapAction”属性,其值为一个URI。这个URI是由SOAP规范进行指定并使用在SOAP消息中。SOAP消息中带有SOAPAction消息头将<soap:operation>元素中的URI作为其值。soapAction属性只有在HTTP binding中才需要。该属性的用法在写该文档时并不十分明确。建议的用法是服务器可以通过这个属性对消息进行路由而不需要对所有的消息进行解析。<soap:operation>还可以有style属性,该属性可以对<soap:binding>中的style属性进行重载。

<operation>元素可以包含<input>,<output>和<fault>元素,这些元素与portTypes段中的相关元素对应。上面的例子中只有<input>元素。这三个元素中都有一个可选的name属性,在本例中,用来对相同名称的操作进行区分。在示例的<input>元素中是<soap:body>元素,该元素指定了SOAP消息体的内容。这个元素有以下三个属性:

Use:这个属性指定了数据是否进行了编码或是字面的意思。字面的意思为SOAP消息体中的数据格式与抽像定义(Types, messages, portTypes段)完全相同。编码表示使用“encodingStyle”属性值决定了编码。

Namespace:每个SOAP消息体都可以有其自己的命名空间来避免名字冲突。在这个属性中指定的URI会完全的使用到返回消息中。

EncodingStyle:为SOAP编码,该属性的URI值为"http://schemas.xmlsoap.org/soap/encoding/"

Document类型的binding

上一节中,<soap:binding>元素中的style属性指定的值为“rpc”,当该属性指定为document时则会改变传输中的数据序列,使用文档传输来代替函数签名。如果使用这种binding方式,则<message>元素中定义了文档格式而非函数签名。作为例子,考虑下面的WSDL片段:

<definitions xmlns:stns="(SchemaTNS)" xmlns:wtns="(WsdlTNS)" targetNamespace="(WsdlTNS)">
<schema targetNamespace="(SchemaTNS)" elementFormDefault="qualified"><element name="SimpleElement" type="xsd:int"/> <element name="CompositElement" type="stns:CompositeType"/><complexType name="CompositeType"><all> <element name='a' type="xsd:int"/> <element name='b' type="xsd:string"/></all> </complexType>
</schema>
<message...> <part name='p1' type="stns:CompositeType"/><part name='p2' type="xsd:int"/> <part name='p3' element="stns:SimpleElement"/> <part name='p4' element="stns:CompositeElement"/>
</message>
...
</definitions>

schema有两个元素:SimpleElement和CompositElement,后一个类型为CompositeType。唯一的<message>元素定义了四个part:p1,类型为CompositeType;p2,类型为int;p3为SimpleElement以及p4为CompositeElement。下面展示了对由style/use确定的四种binding方式的传输格式:

rpc/literal

<operation name="method1" style="rpc" ...> <input> <soap:body parts="p1 p2 p3 p4" use="literal" namespace="(MessageNS)"/> </input>
</operation>

SOAP消息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)" xmlns:stns="(SchemaTNS)"><mns:method1> <mns:p1><stns:a>123</stns:a> <stns:b>hello</stns:b> </mns:p1> <mns:p2>123</mns:p2> <mns:p3><stns:SimpleElement>123</stns:SimpleElement> </mns:p3> <mns:p4> <stns:CompositeElement> <stns:a>123</stns:a> <stns:b>hello</stns:b> </stns:CompositeElement> </mns:p4></mns:method1>
</soapenv:body>

rpc/encoded

<operation name="method1" style="rpc" ...> <input> <soap:body parts="p1 p2" use="encoded" encoding="http://schemas.xmlsoap.org/soap/encoding/" namespace="(MessageNS)"/> </input>
</operation>

SOAP消息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)"> <mns:method1> <p1 HREF="#1" TARGET="_self"/> <p2>123</p2></mns:method1> <mns:CompositeType id="#1"> <a>123</a> <b>hello</b> </mns:CompositeType>
</soapenv:body>

document/literal/type

<operation name="method1" style="document" ...> <input> <soap:body parts="p1" use="literal"> </input>
</operation>

SOAP消息中的格式:

<soapenv:body... xmlns:stns="(SchemaTNS)"> <stns:a>123</stns:a> <stns:b>hello</stns:b>
</soapenv:body>

document/literal/element

<operation name="method1" style="document" ...> <input> <soap:body parts="p3 p4" use="literal"> </input>
</operation>

SOAP消息中的格式:

<soapenv:body... xmlns:stns="(SchemaTNS)"> <stns:SimpleElement>123</stns:SimpleElement> <stns:CompositeElement> <stns:a>123</stns:a> <stns:b>hello</stns:b> </stns:CompositeElement>
</soapenv:body>

document/encoded

<operation name="method1" style="document" ...> <input> <soap:body parts="p1 p2" use="encoded" encoding="http://schemas.xmlsoap.org/soap/encoding/" namespace="(MessageNS)"/> </input>
</operation>

SOAP消息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)"> <mns:CompositeType> <a>123</a> <b>hello</b></mns:CompositeType> <soapenc:int>123</soapenc:int>
</soapenv:body>

<service>和<port>元素

一个service有一组<port>元素。每个<port>元素与binding通常有一对一的对应关系。如果多个<port>元素与同一个<binding>相联系,则需要指定可选的location。

<service name="FOOService"> <port name="fooSamplePort" binding="fooSampleBinding"><soap:address location="http://carlos:8080/fooService/foo.asp"/></port>
</service>

WSDL——Web Service Description Language相关推荐

  1. [WSDL]WSDL(web service document language)简介

    A WSDL document describes a web service using these major elements: (一个WSDL 文件 主要用包含以下4种元素) Element ...

  2. [WSDL] WSDL Web Service 應用 圖文 教學

    最近由於工作的關係,使用到了 WSDL,第一次聽到挺陌生的,但其實接觸了之後發現是個滿方便的服務,還可以自己寫Service提供別人使用喔~ 先來看看W3C怎麼說 http://www.w3.org/ ...

  3. Web Service (二) WSDL详解

    1.Web Service的一些相关概念 web service:远程调用的一种方案.一种解决跨平台.跨语言间的分布式系统的集成(整合)方案 esb:enterprise service bus企业服 ...

  4. 【分布计算环境学习笔记】9 Web Service

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.概述: 在现有的各种异构平台的基础上,构筑一个通用的,与应用无关.语言无关的技术层,各种不同平台之上的应用依 ...

  5. 【REST SOAP】REST和SOAP Web Service的区别比较

    今天遇到一个webservice协议的接口需求,在使用soupUI测试接口连通性的时候,发现使用soupUI新建一个SOAP项目的时候,WSDL链接总是报错打不开(厂家提供的接口规范上写的是SOAP协 ...

  6. 【Java】对Web Service的理解

    WSDL(Web Service Description Language)是描述Web Service的语言. 你会怎样向别人介绍你的Web service有什么功能,以及每个函数调用时的参数呢?你 ...

  7. SOA技术相关介绍(RPC, Web Service, REST,SOAP,JMI)

    概念介绍 SOA(面向服务的软件架构.Service Oriented Architecture),是一种软件设计模式,主要应用于不同应用组件之间通过某种协议来互操作.例如典型的  通信网络协议.因此 ...

  8. Android开发之使用Web Service进行网络编程

    使用Web Service进行网络编程 Android应用通常都是运行在手机平台上,手机系统的硬件资源是有限的,不管是存储能力还是计算能力都有限,在Android系统上开发.运行一些单用户.小型应用是 ...

  9. Making Sense of all these Crazy Web Service Standards

    转自: https://www.infoq.com/articles/ws-standards-wcf-bustamante It has been eight years now since SOA ...

最新文章

  1. android 开发使用adb操作sqlite
  2. python官网下载步骤linux-linux下安装python
  3. VMware Workstation 与 Hyper-V 不兼容。请先从系统中移除 Hyper-V 角色
  4. Emerged strategy 涌现战略
  5. C和指针笔记 3.8 static关键字
  6. OpenCL列举平台列表以及平台属性信息
  7. 「旁门右道」CURL持久连接技巧
  8. 云服务器 ECS 建站教程:部署Linux主机管理系统WDCP
  9. 【UI插件】简单的日历插件(下)—— 学习MVC思想
  10. 错误:cc1: error: unrecognized command line option “-m32”
  11. 【转】winIO的解释与使用
  12. ImageOptim-无损图片压缩Mac版
  13. switch更新主机服务器维护,switch更新链接不到服务器
  14. Rails PayPal 支付对接
  15. YB1205B 外置MOS异步升压恒流LED驱动控制器
  16. wordpress后台样式_如何在WordPress中以不同的方式设置单个类别的样式
  17. 券商单向视频见证开户全面开放!菊风泛金融单向视频开户一体化解决方案极速助力
  18. 成交量、持仓量与价格运动的关系
  19. Android常见内存泄漏以及解决办法
  20. 利用策略组限制特定软件的运行

热门文章

  1. 一月到十二月的英文简写和英文单词
  2. 连续支付(周期扣款)功能开发及注意事项
  3. 【论文学习】6、Wi-Fi中基于前导码的包检测:一种深度学习方法
  4. Ubuntu Linux 查看、编辑、比较二进制文件
  5. Scrapy中的item和pipline
  6. [软件更新]SRS Audio Sandbox v1.9.0.4 汉化版
  7. vue element 确认弹框中显示图片(message里)
  8. cocos2dx-lua项目的构建、编译细则
  9. 申请注册GMAIL的免费企业邮箱
  10. APP测试概念/Appium实战