WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展示[WS标准篇]

原文: WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展示[WS标准篇]

元数据其实是服务终结点的描述,终结点由地址(Address)、绑定(Binding)和契约(Contract)经典的ABC三要素组成。认真阅读过《WCF技术剖析(卷1)》的读者相对会对这三要素的本质有一个深入的认识:地址决定了服务的位置并实现相应的寻址机制;契约描述了消息交换模式(Message Exchange Pattern: MEP)以及消息的结构(Schema);绑定则经过建立信道栈实现对消息的编码、传输和基于某些特殊的功能(好比实现事务、可靠传输以及基于消息的安全)对消息做出的处理。 html

服务的消费者经过获取服务端发布的元数据,并在此基础上重建终结点,才能取保请求:消息被发送到准确的目标地址;采用服务端指望的消息交换模式和并生成服务端可以识别的消息结构;使用相匹配的消息编码方式以确保服务端可以对接收到的消息进行正常解码;使用一致的传输协议以实现消息的正常传输;对消息进行与服务端一致性的处理以确保对事务、可靠传输、消息安全等协议的实现。 安全

WCF是基于SOA构建的一个分布式通讯平台,而SOA一个重要的特性就是实现跨平台的互操做。元数据是确保服务消费者正常调用目标服务(可能部署于异质平台),因此元数据自己须要采用一种开放的标准来表示。目前,元数据具备三种比较典型的表示方式: 网络

  • XSD经过XML Schema的形式描述组成消息的数据类型的XML结构;
  • WSDL经过一个完整的Web Service Description Language文档对服务进行全面的描述,即包括抽象的功能,也包括具体的细节;
  • WS-Policy策略:经过WS-Policy规范以断言(Assertion)形式对服务能力和特性进行描述。

对跨平台互操做的实现不只仅要求承载服务描述信息的元数据自己采用一种开放的标准或者规范来表示,甚至要求元数据交换(Metadata Exchange:MEX)一样按照厂商共同遵照的规范来进行。在WS-*规范体系中,WS-Metadata Exchange(WS-MEX)为元数据的交换进行了标准化的规范。WS-MetadataExchange(如下简称WS-MEX)规范了与终结点(这里是广义的Web服务终结点,与具体的技术无关)如何表示成一个WS-Transfer资源,并被嵌入到WS-Addressing终结点引用(Endpoint Reference)中,以及元数据如何被相应的Web服务终结点获取。简言之,WS-MEX是一个关于如何进行元数据交换的WS规范。WS-MEX和其余的WS-*规范一块儿,好比WSDL、WS-Addressing、WS-Transfer、WS—Policy等一块儿组成了一个完整的描述Web服务元数据和元数据交换的规范体系,在正式介绍WS-MEX以前,先来大概了解一些其余的这些辅助性WS-*规范。 数据结构

1、WS-Policy架构

一个Web服务(这里指广义的、与技术平台无关的Web服务)除了实现经过服务契约定义的业务功能以外,为了实现一些额外的功能(好比安全、事务和可靠传输等),还须要具备一些与业务无关的行为(Behavior)和能力(Capability),咱们能够将这些统称为Web服务的策略(Policy)。WS-Policy提供了一个基于XML的框架模型和语法用于描述Web服务的能力、要求和行为属性。 app

WS-Policy属于WS-*体系中的一个基础性规范,其规范自己不会被单独使用,而是服务于其余的WS规范(咱们通常称这些为Domain Specific规范,好比WS-Transaction、WS-Reliable Messaging和WS-Security等)提供一种统一的策略描述。 框架

W3C前后在2006年和2007年推出了两个版本的WS-Policy规范,即WS-Policy 1.2和WS-Policy 1.5。在这里,咱们仅仅是正对最新的WS-Policy版本(1.5)来简单介绍一些一个完整的WS策略具备怎样的结构,对于但愿深刻了解WS-Policy的读者,能够经过后面的地址下载到W3C的官方文档:http://www.w3.org/TR/ws-policy/分布式

WS-Policy采用一个基于XML的策略表达式(Policy Expression)表示一个策略,在投入到对具体策略定义的介绍以前,咱们不妨先来看看一个典型的策略表达式的定义。下面XML片段表示的策略表达式来自于WS-Security,这是一个基于如何实现基于消息安全的WS规范。它体现的含义是:对消息的主题部分采用签名仍是加密。post

   1: (01)<wsp:Policy
   2:         xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
   3:         xmlns:wsp="http://www.w3.org/ns/ws-policy" >
   4: (02)   <wsp:ExactlyOne>
   5: (03)     <wsp:All>
   6: (04)        <sp:SignedParts>
   7: (05)           <sp:Body/>
   8: (06)        </sp:SignedParts>
   9: (07)     </wsp:All>
  10: (08)     <wsp:All>
  11: (09)        <sp:EncryptedParts>
  12: (10)           <sp:Body/>
  13: (11)        </sp:EncryptedParts>
  14: (12)     </wsp:All>
  15: (13)   </wsp:ExactlyOne>
  16: (14) </wsp:Policy>

上面这个XML采用一种标准的形式(WS-Policy还定义了一种简写的策略表示方式)定义一个策略,接下来咱们就此为基础介绍一个完整的策略表达式具备怎样的结构。 网站

在一个基于Web服务的系统中,策略体现的对Web服务相关实体要求(Requirements)、能力(Capabilities)和特性(Characteristics)等行为属性的表示。WS-Policy经过断言(Assertion)的形式来表示这些单一的行为属性,而后经过必定的规则将相关的策略断言有机的组合在一块儿,以实现对整个Web服务目标实体的完整描述。

按照WS-Policy 1.5的规定,全部的策略元素均定义在http://www.w3.org/ns/ws-policy命名空间下,一个完整策略经过一个基于XML的策略表达式描述。一、

一、策略表达式(Policy Expression)

一个策略表达式是一个XML信息集(XML InfoSet),描述了一个完整的策略。策略表达式具备两个不一样的表示形式:标准形式(Normal Form)和简写形式(Compact Form)。一个策略表达式是一个策略选择项(Policy Alternative)的集合。咱们要求知足某个策略,意味着咱们需要知足该集合的至少一个策略选择项。

二、策略选择项(Policy Alterative)

通常状况下,策略每每是承载一些确保服务正常调用(说得更加具体一点,就是确保Web服务终结点可以正常交互)的条件信息。服务的消费者在进行正常的服务消费以前,须要保证提供这些必备的前提条件。对于服务提供者来讲,针对某个具体的应用场景的时候,会提供一到多个不一样的选择项。好比咱们上面给出的例子,在应用基于消息的安全策略的时候,根据不一样安全级别的需求,能够选择对消息的主体部分进行签名或者加密。

这些单一的选择项被称为策略选择项(Policy Alternative),对于上面给出的策略表达式,(03)-(07)和(08)-(12)定义两个策略选择项,表明对消息主体进行签名仍是加密。一个策略选择项由零到多个策略断言经过相应的策略操做符组合在一块儿。

三、策略断言(Policy Assertion)

在WS-Policy规范下,Web服务实体某个单一的行为属性最终经过一个策略断言表示。而一个策略断言由一个好比的断言类型(Assert Type)和一组可选的断言参数(Assert Parameter)组成。断言类型经过一个有效名称(Qualified Name: QName)表示,即命名空间和本地名称(Local Name)的组合。在定义了两个策略断言:(04)-(06)和(09)-(11),其断言类型分别为:sp:SignedParts和sp:EncryptedParts。

一个最简单的策略断言能够仅仅由一个包含断言类型的空XML元素构成,咱们也能够为这个XML元素添加用于辅助描述该断言的XML属性(Attribute)和XML子元素,咱们把这些策略辅助描述信息称为断言参数。

一个策略断言能够很简单(一个空XML元素),也能够定义的很复杂,这取决于具体的策略描述对象。一个比较极端的策略断言是:将一个完整的策略表达式做为其子元素,咱们把这种状况称为策略断言嵌套(Policy Assetion Nesting)。嵌套的策略断言的结构能够经过下面的XML表示:

   1: (01) <Assertion>
   2: (02)   …
   3: (03)   ( <wsp:Policy></wsp:Policy> )?
   4: (04)   …
   5: (05) </Assertion>

四、策略操做符(Policy Operator)

一个策略选择项又由零(也就是说能够定义空的策略选择项)到多个策略断言经过必定的规则构成,在这里对策略断言的组合规则经过策略操做符来体现。策略操做符体现的是这样一种含义:请求者采用怎样的方式去知足构成策略选择项的全部策略断言,须要知足全部的断言呢,仍是仅仅须要知足其中某一个?

WS-Policy定义了两种主要的策略操做符(实际上Policy自己就属于一个策略操做符)ExactlyOne和All。根据名称咱们不难猜出,ExactlyOne表示仅仅须要知足断言集合的某一个元素便可,而All意味着须要知足断言集合中的全部元素。

此外,因为wsp:ExactlyOne表示的是“知足其中之一”的意思,这和策略和策略选择项之间体现的关系吻合,因此在标准形式体现的策略表达式中,全部的策略选择项均纳于wsp:ExactlyOne操做符之中。

image

1 策略表达式结构图

整个策略表达式的结构,即策略、策略选择项和策略断言之间的关系,大致能够经过图1表示。关于WS-Policy中对策略表达式的规定,还一个其余一些额外的内容,好比策略的识别(Policy Identifying)、策略简写形式(Compact Form)等,在这里就再也不一一介绍了,有兴趣的读者能够下载WS-Policy 1.5的官方文档(http://www.w3.org/TR/ws-policy/)。

2、WS-Transfer

在Web服务的世界中,不少资源(Resource)均可以经过XML的形式来表示,并经过WS-Addressing规范的方式进行寻址。而WS-Transfer就是这样的一个WS规范:规定如何采用基于SOAP的方式实现可寻址的(Addressable)Web服务资源的获取、更新、删除和建立。接下来对WS-Transfer的介绍,假设你对WS-Addressing和SOAP有了一个基本的了解。对这两个规范不是很熟悉的读者,能够从W3C的网站上下载官方文档。此外,在《WCF技术剖析(卷1)》的第2章和第6章对WS-Addressing 1.0和SOAP 1.2进行了归纳性的介绍。

虽然咱们能够经过不少不一样的方式(好比REST)对资源进行获取和更新,WS-Transfer彻底创建在基于SOAP基础上。WS-Transfer的主要内容集中在对4个基本资源操做上面:Get、Put、Delete和Create,分别实现对资源的获取、更新、删除和建立。W3C分别在2006年3月份和9月份前后推出了两个版本的WS-Transfer,咱们接下来的介绍彻底基于最新版本的WS-Transfer,你能够从后面的地址获取正式的官方文档:http://www.w3.org/Submission/WS-Transfer/

因此基于WS-Transfer元素定义在http://schemas.xmlsoap.org/ws/2004/09/transfer命名空间下。接下来咱们着重对上述的4个资源进行介绍。

一、资源的获取:Get

请求者创结基于Get操做的SOAP消息像目标地址发送请求以获取相应的资源,这样的请求消息必须具备以下的格式。

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/Get
   5:     </wsa:Action>
   6:     <wsa:MessageID>xs:anyURI</wsa:MessageID>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body ...>
  11:
  12:   </s:Body>
  13: </s:Envelope>

WS-Addressing报头Action的值必须是http://schemas.xmlsoap.org/ws/2004/09/transfer/Get,消息的主体(Body)部分为空。资源接受Get请求后,采用以下结构的SOAP消息进行回复,Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse,表示资源的XML必须做为消息主体的第一个子元素。

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse
   5:     </wsa:Action>
   6:     <wsa:RelatesTo>xs:anyURI</wsa:RelatesTo>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body>
  11:     xs:any
  12:
  13:   </s:Body>
  14: </s:Envelope>

二、资源的更新:Put

请求者建立基于Put操做的SOAP消息,提供新的资源内容向目标地址发送请求,以更新某个现有的资源。Put请求消息必须具备以下的格式:

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/Put
   5:     </wsa:Action>
   6:     <wsa:MessageID>xs:anyURI</wsa:MessageID>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body>
  11:     xs:any
  12:     ...
  13:     </s:Body>
  14:   </s:Envelope>

Put请求消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/Put,表示资源的XML必须做为消息主体的第一个子元素。资源接受Put请求后,经过具备以下格式的SOAP回复请求。回复消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/PutResponse,如何彻底采用请求者提供的资源对现有的目标资源进行更新,那么回复消息的主体部分为空,不然将更新后的资源以XML的形式置于回复消息主体部分的第一个子元素中。

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/PutResponse
   5:     </wsa:Action>
   6:     <wsa:RelatesTo>xs:anyURI</wsa:RelatesTo>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body>
  11:     xs:any ?
  12:   </s:Body>
  13: </s:Envelope>

三、资源的删除:Delete

请求者建立基于Delelte操做的SOAP消息向目标地址发送请求,以删除某个现有的资源。Delelte请求消息必须具备以下的格式:

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete
   5:     </wsa:Action>
   6:     <wsa:MessageID>xs:anyURI</wsa:MessageID>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body/>
  11: </s:Envelope>

Delete请求消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete,消息主体部分为空。资源接受Delete请求后,经过具备以下格式的SOAP回复请求。回复消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/DeleteResponse,回复消息的主体部分为空。

四、资源的建立:Create

请求者建立基于Create操做的SOAP消息向目标地址发送请求,以建立一个新的资源。Create请求消息必须具备以下的格式:

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/Create
   5:     </wsa:Action>
   6:     <wsa:MessageID>xs:anyURI</wsa:MessageID>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body>
  11:     xs:any
  12:     ...
  13:   </s:Body>
  14: </s:Envelope>

Create请求消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/Create,新的资源内容以XML的形式做为消息主体部分的第一个子元素。资源工厂接受Create请求后,经过具备以下格式的SOAP回复请求。回复消息的Action报头为http://schemas.xmlsoap.org/ws/2004/09/transfer/CreateResponse,并将新建立资源的WS-Addressing的终结点引用(Endpoint Reference)做为回复消息主体部分的第一个子元素。若是,最终被更新的资源内容和请求者提供的不一致,本更新的资源内容须要做为回复消息主体部分的第二个子元素返回。

   1: <s:Envelope>
   2:   <s:Header>
   3:     <wsa:Action>
   4:       http://schemas.xmlsoap.org/ws/2004/09/transfer/CreateResponse
   5:     </wsa:Action>
   6:     <wsa:RelatesTo>xs:anyURI</wsa:RelatesTo>
   7:     <wsa:To>xs:anyURI</wsa:To>
   8:
   9:   </s:Header>
  10:   <s:Body>
  11:     <wxf:ResourceCreated>endpoint-reference</wxf:ResourceCreated>
  12:     xs:any?
  13:   </s:Body>
  14: </s:Envelope>

3、 WSDL

WSDL,全称Web服务描述语言(Web Service Description Language),是采用XML格式的形式对Web服务的描述。WSDL将一个Web服务定义成一组终结点的集合,而每个终结点包含一系列基于消息(Message)的操做(Operation)。这些抽象的操做和消息最终和相应的协议以及消息格式绑定。

虽然W3C在2007年6月份就正式出台了WSDL 2.0版本,并将其做为官方推荐,可是该版本并无获得普遍的推广,并无被主流的厂商彻底支持。现在,WCF彻底支持的仍是WSDL 1.1版本,因此接下来咱们将针对这个版本对WSDL做一个简单的介绍,对于但愿了解WSDL1.1的读者能够从后面的地址下载官方文档:http://www.w3.org/TR/wsdl。就WSDL描述对象的性质,咱们大致能够将全部WSDL的元素划分为如下两类:

  • 抽象元素:好比经过XSD表示的数据类型;用于承载数据信息的消息;经过对关联的消息按照某种消息交换模式组合而成的操做等;
  • 具体元素:好比将相应的操做和具体的网络协议和消息格式进行绑定等。

为了有效地了解WSDL的结构,咱们首先来看看一段直接从官方文档上拷贝出来的WSDL文档:

   1: <?xml version="1.0"?>
   2: <definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl" xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/">
   3:   <types>
   4:     <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema">
   5:       <element name="TradePriceRequest">
   6:         <complexType>
   7:           <all>
   8:             <element name="tickerSymbol" type="string"/>
   9:           </all>
  10:         </complexType>
  11:       </element>
  12:       <element name="TradePrice">
  13:         <complexType>
  14:           <all>
  15:             <element name="price" type="float"/>
  16:           </all>
  17:         </complexType>
  18:       </element>
  19:     </schema>
  20:   </types>
  21:   <message name="GetLastTradePriceInput">
  22:     <part name="body" element="xsd1:TradePriceRequest"/>
  23:   </message>
  24:   <message name="GetLastTradePriceOutput">
  25:     <part name="body" element="xsd1:TradePrice"/>
  26:   </message>
  27:   <portType name="StockQuotePortType">
  28:     <operation name="GetLastTradePrice">
  29:       <input message="tns:GetLastTradePriceInput"/>
  30:       <output message="tns:GetLastTradePriceOutput"/>
  31:     </operation>
  32:   </portType>
  33:   <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
  34:     <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
  35:     <operation name="GetLastTradePrice">
  36:       <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
  37:       <input>
  38:         <soap:body use="literal"/>
  39:       </input>
  40:       <output>
  41:         <soap:body use="literal"/>
  42:       </output>
  43:     </operation>
  44:   </binding>
  45:   <service name="StockQuoteService">
  46:     <documentation>My first service</documentation>
  47:     <port name="StockQuotePort" binding="tns:StockQuoteBinding">
  48:       <soap:address location="http://example.com/stockquote"/>
  49:     </port>
  50:   </service>  
  51: </definitions>

上面给出的是一个很标准的WSDL文档,从中咱们能够看出它由五个子元素构成:Type、Message、PortType、Binding和Service。这五大元素构成一个了一个完成得WSDL,如今能够就对它们逐个进行介绍。

一、Types:经过XSD表示的数据类型的集合

WSDL并无属于本身的数据类型定义规范,而是直接采用XSD做为数据定义的语言。上面的WSDL文档经过XSD定义了两个XML元素,元素名称分别为TradePriceRequest和TradePrice,命名空间为http://example.com/stockquote.xsd。从XSD的定义咱们不难看出,这两个类型分别是字符串和浮点数类型。

   1: <types>
   2:   <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema">
   3:     <element name="TradePriceRequest">
   4:       <complexType>
   5:         <all>
   6:           <element name="tickerSymbol" type="string"/>
   7:         </all>
   8:       </complexType>
   9:     </element>
  10:     <element name="TradePrice">
  11:       <complexType>
  12:         <all>
  13:           <element name="price" type="float"/>
  14:         </all>
  15:       </complexType>
  16:     </element>
  17:   </schema>
  18: </types>

二、Message: 通讯数据的载体

Web服务采用基于消息的通讯方式,因此消息是通讯数据的载体。WSDL的message元素用于定义全部定义终结点操做的消息的结构。WSDL的消息是一个具备惟一标识(经过Name属性)的XML元素,一般利用Types结点中定义的数据类型来描述。上面的WSDL定义了两个消息,名称分别为GetLastTradePriceInput和GetLastTradePriceOutput,消息主体部分的结构经过引用定义在Types结点中的XML元素的有效名称(QName:命名空间+本地名称)。

   1: <message name="GetLastTradePriceInput">
   2:   <part name="body" element="xsd1:TradePriceRequest"/>
   3: </message>
   4: <message name="GetLastTradePriceOutput">
   5:   <part name="body" element="xsd1:TradePrice"/>
   6: </message>

三、PortType:相关操做的集合

一个服务逻辑上有一系列关联的操做组成,从消息交换的角度上讲,操做进行关联的消息按照相应的消息交换模式的有机组合。WSDL的PortType表示的就是这么一个操做的集合,反映在XML结构上,就是一组operation元素的基本。每个operation XML元素表明一个单一的操做,它经过一个或者多个消息组合而成。消息的不一样组合方式反映了操做采用的不一样消息交换模式(MEP: Message Exchange Pattern)。上面给出的WSDL经过以下的XML片段定义了一个仅仅包含一个操做的PortType。

   1: <portType name="StockQuotePortType">
   2:   <operation name="GetLastTradePrice">
   3:     <input message="tns:GetLastTradePriceInput"/>
   4:     <output message="tns:GetLastTradePriceOutput"/>
   5:   </operation>
   6: </portType>

在《WCF技术剖析(卷1)》第4章对服务操做的介绍中,咱们说服务契约中的操做契约本质上就是定义了操做采用的消息交换模式,以及消息的格式。在这里你会进一步获得证明,实际上,当某个WCF服务经过WSDL的形式发布出来,服务契约映射的部分就是PortType。WCF支持三种典型的消息交换模式:单工(One-way)请求回复(Request-Reply)和双工(Duplex)。实际上,双工模式是由前面两种模式组合而成,单工(One-way)和请求-回复(Request-Reply)模式才是基元消息交换模式。除了这两种基元模式,WSDL还对另外两种消息交换模式提供支持:恳请-回复(Solicit-Response)和通知(Notification)模式。

PortType中的每个操做均由输入(Input)和输出(Output)消息的不一样组合方式定义,而这种对输入、输出消息的不一样组合就是对某种消息交换模式的反映。接下来,咱们站在服务端终结点的角度,来介绍上述的4中消息交换模式:

单工(One-way)

单工消息交换模式下,终结点仅仅是接收来自客户端的请求。单向操做仅仅包含一个输入消息,在WSDL中的表示以下:

   1: <wsdl:definitions ... >
   2:   <wsdl:portType ... >*
   3:     <wsdl:operation name="nmtoken">
   4:       <wsdl:input name="nmtoken"? message="qname"/>
   5:     </wsdl:operation>
   6:   </wsdl:portType >
   7: </wsdl:definitions>

请求-回复(Request-Reply)

请求-回复消息交换模式下,终结点接收来自客户端的请求,并向发送匹配的回复消息。请求-恢复操做经过输入消息和输出消息的有序组合表示,在WSDL中的表示以下:

   1: <wsdl:definitions>
   2:   <wsdl:portType>*
   3:     <wsdl:operation name="nmtoken" parameterOrder="nmtokens">
   4:       <wsdl:input name="nmtoken"? message="qname"/>
   5:       <wsdl:output name="nmtoken"? message="qname"/>
   6:       <wsdl:fault name="nmtoken" message="qname"/>*
   7:     </wsdl:operation>
   8:   </wsdl:portType>
   9: </wsdl:definitions>

恳请-回复(Solicit-Response)

在恳请-回复消息交换模式下,终结点先向客户端到发送请求,并接收来自客户端的回复,这和请求-回复模式正好相反。恳请-回复操做由输出消息和输入消息的有序组合表示,在WSDL中的表示以下:

   1: <wsdl:definitions>
   2:   <wsdl:portType>*
   3:     <wsdl:operation name="nmtoken" parameterOrder="nmtokens">
   4:       <wsdl:output name="nmtoken"? message="qname"/>
   5:       <wsdl:input name="nmtoken"? message="qname"/>
   6:       <wsdl:fault name="nmtoken" message="qname"/>*
   7:     </wsdl:operation>
   8:   </wsdl:portType>
   9: </wsdl:definitions>

通知(Notification):

在通知消息交换模式下,终结点仅仅向客户端发送请求,这和单向模式正好相反。通知操做由单一的输出消息组成,在WSDL中的表示以下:

   1: <wsdl:definitions>
   2:   <wsdl:portType>    *
   3:     <wsdl:operation name="nmtoken">
   4:       <wsdl:output name="nmtoken"? message="qname"/>
   5:     </wsdl:operation>
   6:   </wsdl:portType>
   7: </wsdl:definitions>

注:对于请求-回复和恳请-回复消息交换模式来讲,双方除了进行正常的消息交换以外,当错误发生,须要将错误信息封装成消息发送给对方。因此,这两种类类型的操做除了输出消息和输入消息的描述以外,还具备错误消息的描述。错误消息在操做中经过<wsdl:fault/〉表示。

四、Bindings:消息、操做与协议、格式的绑定

上面介绍WSDL的三个元素主要从抽象的角度对数据类型、消息和操做进行描述,要建立服务于具体消息交换场景的终结点,还须要将这需抽象的描述和具体的消息格式(Format)和网络协议绑定,好比SOAP、HTTP-GET和MIME等。

在这里,咱们颇有必要强调“终结点”,本节咱们提到的终结点在大部分场景中都是指与技术无关的、用于进行消息交换的“端口”。而咱们WCF中提到的终结点,能够当作是这样一个通用的终结点在具技术平台中的实现。WCF的终结点由地址、绑定和契约构成,结合WSDL咱们不难看出,Type、Message和PortType是对契约的描述。而绑定,就其语言和功能上讲,就是实现了抽象的描述和具体的协议(网络传输协议、SOAP和WS-*规范等)之间的绑定。在WSDL中,Bindings元素具备同样的功能。

在WSDL中,咱们能够经过不少绑定扩展实现与某种协议的绑定,而最为常见的是基于SOAP 1.1和SOAP 1.2的绑定。上面给出的WSDL中定义了一个典型的基于SOAP 1.1的绑定(SOAP 1.1和SOAP 1.2绑定的命名空间分别为http://schemas.xmlsoap.org/wsdl/soap/和http://schemas.xmlsoap.org/wsdl/soap12/)。

   1: <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
   2:   <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
   3:   <operation name="GetLastTradePrice">
   4:     <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
   5:     <input>
   6:       <soap:body use="literal"/>
   7:     </input>
   8:     <output>
   9:       <soap:body use="literal"/>
  10:     </output>
  11:   </operation>
  12: </binding>

以上面这个SOAP绑定为例,一个绑定经过name属性(name="StockQuoteSoapBinding")定义其惟一标识,并经过type属性和定义个PortType(type="tns:StockQuotePortType")进行关联。该SOAP绑定定义了消息采用的风格(style="document",另一个选项是“rpc”)和传输协议(transport="http://schemas.xmlsoap.org/soap/http")。在操做级别,定义了操做反映在SOAP Action报头的值(soapAction="http://example.com/GetLastTradePrice"),以及输入和输出消息的主体部分采用的编码方式(use="literal")。

五、Service:相关终结点的集合

因为一个Web服务最终以终结点的方式暴露出来,因此WSDL最终体如今对终结点集合的描述,这里介绍的WSDL最后一个元素<Service/>本质上就是对基于该Web服务的一组相关终结点的定义。咱们照例将上面给出的WSDL的Service相关部分提取出来,根据具体的例子分析Service结点应有的结构。

   1: <service name="StockQuoteService">
   2:   <documentation>My first service</documentation>
   3:   <port name="StockQuotePort" binding="tns:StockQuoteBinding">
   4:     <soap:address location="http://example.com/stockquote"/>
   5:   </port>
   6: </service>

<Service>经过name属性(name="StockQuoteService")定义了服务的惟一标识。该节点具备一个可选的<documentation>元素,能够经过单纯的文本或者XML为该服务定义一些可读的说明性的描述。<Service>结点最重要的就是一组<port>元素,而每个port即表明着一个终结点。每一个具备一个name属性定义终结点的名称,经过binding属性引用相应的定义得binding。并经过相应的绑定扩展定义终结点的地址,在这里终结点的地址经过SOAP绑定定义(<soap:address location="http://example.com/stockquote"/>)。

图2反映了WSDL5个元素之间的关系。对于表示一个终结点对象<port>元素来讲,它具备一个地址(Address)和关联着一个绑定(Binding),而绑定对象关联着一个PortType。而一个PortType实际上对应的着WCF中的契约(Contract)。因此,WCF下的终结点由地址、绑定和契约三要素组成在这里也获得进一步的反映,实际上,WCF自己就是按照WS开放标准设计的。

image

图2 WSDL5个元素之间的引用关系

4、 WS-MEX

WCF的元数据结构体系构建在一个开放的标准之上,这个标准就是WS-Metadata Exchange,简称WS-MEX。WS-MEX是WS-*你们庭中的一名重要成员,最新的版本是1.1,但愿全面了解WS-MEX 1.1规范的读者能够从后面的地址下载官方文档:http://specs.xmlsoap.org/ws/2004/09/mex/WS-MetadataExchange.pdf。规范了如何将基于Web终结点的元数据表示成一个WS-Transfer资源;如何将元数据内嵌于WS-Addressing的终结点引用(Endpoint Reference)中;以及如何获取某个Web服务终结点的元数据。WS-MEX主要的目的在规范元数据的获取,它提供了以下两种不一样的方式去获取Web服务终结点的元数据:WS-Transfer Get和Get Metadata。此外,基于WS-MEX的元素定义在http://schemas.xmlsoap.org/ws/2004/09/mex命名空间下。

一、经过WS-Transfer GET操做获取元数据

我之因此在正式介绍WS-MEX以前会先对WS-Transfer做一个简单的讨论,使由于采用WS-Transfer的Get操做是元数据的主要获取方式之一。经过前面的介绍,咱们知道了WS-Transfer旨在规范如何获取、更新、删除和建立Web服务资源。元数据自己就能够做为一种典型的Web服务资源,那么采用WS-Transfer无疑是一种最直接的选择。

元数据的提供者将元数据做为一种Web服务资源经过一个基于WS-Transfer的终结点暴露出来,请求者向该终结点发送WS-Transfer Get请求,以回复消息的形式得到所需的元数据。下面就是一个典型的基于SOAP 1.1的WS-Transfer Get请求消息,请求的目标地址就是元数据资源对应的终结点。

   1: <s11:Envelope xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa10="http://www.w3.org/2005/08/addressing">
   2:   <s11:Header>
   3:     <wsa10:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</wsa10:Action>
   4:     <wsa10:To>http://services.example.org/stockquote/metadata</wsa10:To>
   5:     <wsa10:ReplyTo>
   6:       <wsa10:Address>http://client.example.org</wsa10:Address>
   7:     </wsa10:ReplyTo>
   8:     <wsa10:MessageID>urn:uuid:1cec121a-82fe-41da-87e1-3b23f254f128</wsa10:MessageID>
   9:   </s11:Header>
  10:   <s11:Body />
  11: </s11:Envelope>

针对上面一个基于WS-Transfer Get操做的元数据请求,可能会获得以下一个标准的WS-Transfer Get回复消息,请求的元数据被置于SOAP消息的主体部分。

   1: <s11:Envelope xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:mex="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
   2:   <s11:Header>
   3:     <wsa10:Action> http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</wsa10:Action>
   4:     <wsa10:To>http://client.example.org</wsa10:To>
   5:     <wsa10:RelatesTo>urn:uuid:1cec121a-82fe-41da-87e1-3b23f254f128</wsa10:RelatesTo>
   6:   </s11:Header>
   7:   <s11:Body>
   8:     <mex:Metadata>
   9:       <mex:MetadataSection Dialect="http://schemas.xmlsoap.org/wsdl/">
  10:         <wsdl:definitions name="StockQuote" ...>
  11:           ...
  12:         </wsdl:definitions>
  13:       </mex:MetadataSection>
  14:       <mex:MetadataSection Dialect="http://www.w3.org/2001/XMLSchema" Identifier="http://services.example.org/stockquote/schemas">
  15:         <mex:Location>http://services.example.org/stockquote/schemas</mex:Location>
  16:       </mex:MetadataSection>
  17:       <mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2004/09/policy" Identifier="http://services.example.org/stockquote/policy">
  18:         <mex:MetadataReference>
  19:           <wsa10:Address>http://services.example.org/stockquote/policy</wsa10:Address>
  20:         </mex:MetadataReference>
  21:       </mex:MetadataSection>
  22:     </mex:Metadata>
  23:   </s11:Body>
  24: </s11:Envelope>

从上面提供的包含元数据的SOAP消息中,咱们能够看到:全部的元数据均包含在<Metadata>结点中。<Metadata>结点其实是一个<MetadataSection>元素的集合,具体的元数据定一个在相应的<MetadataSection>结点下,元数据的表现形式经过Dialect属性定义。经过Dialect表示的元数据表示形式被称为元数据方言。

元数据方言(Dialect)

在本章开始的时候,咱们就谈到Web服务终结点元数据具备三种典型的表现形式:WSDL、XSD和WS-Policy。在看看咱们上面给出的包含元数据的SOAP消息中,<Metadata>结点下三个<MetadataSection>分别就对应这三种形式的元数据。第一个<MetadataSection>经过内联的方式直接嵌入一个WSDL文档;第二个<MetadataSection>以地址的方式指定了一个XML Schema;第三个<MetadataSection>以终结点引用的方式指定了一个WS-Policy策略。<MetadataSection>的Dialect以一个决定地址的形式指明了元数据体现的形式,即元数据方言(Dialect)。图3展示了Metadadata、MetadataSection以及这三种典型元数据方言之间的关系。在WS-MEX中为如下5种方言定义了相应的URI:

注:WS-Policy Attachment是另一份WS规范,用于如何将WS-Policy中定义的策略和具体的WS规范(Domain-Specific WS Specification)进行关联。MEX表明通常意义的元数据,它包含基于某种具体方言的元数据。

image 图3 Metata、MetadataSection与三种典型的元数据表现形式

二、经过Get Metadata操做获取元数据

经过WS-Transfer Get的方式获取Web服务终结点的元数据的前提是直接将元数据自己做为Web服务资源。可是对于某些特殊的场景,这种方式不不太适合。好比,多个元数据资源关联到同一个元数据终结点,但愿经过向该终结点发送请求获取全部相关的元数据;并且,并非在任何状况下都能将终结点的元数据做为一个能够被寻址(基于WS-Addressing)的Web服务资源。为了在这些场景中解决元数据的获取,WS-MEX提出了另外一种替换的元数据获取方式:Get Metadata。Get Metadata操做请求的SOAP消息具备以下的结构要求(?表示0或1个前置元素):

   1: [action] 
   2: http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata/Request 
   3: [Body] 
   4: <mex:GetMetadata ...> 
   5: (<mex:Dialect>xs:anyURI</mex:Dialect> 
   6: (<mex:Identifier>xs:anyURI</mex:Identifier>)? 
   7: )? 
   8: </mex:GetMetadata>

当服务终结点接受了Get Metadata请求后,生成相应的回复消息并将元数据置于消息的主体部分。Get Metadata回复消息具备以下的结构要求:

   1: [action] 
   2: http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata/Response 
   3: [Body] 
   4: <mex:Metadata ...> 
   5: ... 
   6: </mex:Metadata>
做者: Artech
出处: http://artech.cnblogs.com 本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。
相关文章
相关标签/搜索