享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

WS-Addressing Message Addressing Properties

Posted on 2006-06-24 15:03  idior  阅读(5004)  评论(3编辑  收藏  举报

相对EndpointReference而言,个人认为在WS-Addressing规范中Message Addressing Properties的作用显的更加重要,下面将对它做详细介绍。与EndpointReference用于描述服务的地址不同,Message Addressing Properties作为SOAP Head的扩展将包含在每一个SOAP 消息中,用于该消息的寻址。首先来看一下它的XML Infoset:

<wsa:To>xs:anyURI</wsa:To> ?
<wsa:From>wsa:EndpointReferenceType</wsa:From> ?
<wsa:ReplyTo>wsa:EndpointReferenceType</wsa:ReplyTo> ?
<wsa:FaultTo>wsa:EndpointReferenceType</wsa:FaultTo> ?
<wsa:Action>xs:anyURI</wsa:Action>
<wsa:MessageID>xs:anyURI</wsa:MessageID> ?
<wsa:RelatesTo RelationshipType="xs:anyURI"?>xs:anyURI</wsa:RelatesTo> *
<wsa:ReferenceParameters>xs:any*</wsa:ReferenceParameters> ?

下面这张图更加清楚的表示出Message Addressing Properties与SOAP 消息的关系。

                        

其中<wsa:MessageID>用于标识一个消息,而<wsa:RelatesTo>表示该消息与另一消息关系,元素值是另一消息的MessageID。<wsa:RelatesTo>元素对实现异步消息交换有很重要的作用,这点在后面的文章中会具体介绍。
我把剩下的Message Addressing Properties分成了两类属性,一类(Go)指出该消息的去向,另一类(Back)为该消息可能存在的返回消息提供寻址功能。也就是说Go类型的属性才与该消息的寻址直接相关,而Back类型的属性对消息自身的寻址没有任何影响,纯粹是为了与该消息对应的返回消息寻址所用。显而易见,如果该消息不存在返回消息,那么Back类型的属性就不需要了。下面具体介绍每一类属性。

Go类型的属性用于消息自身的寻址,自然也是最重要的,在了解了EndpointReference的概念后,对于其中的<wsa:To><wsa:ReferenceParameters>属性也就很容易理解了。把消息所请求的Service的EndpointReference的值搬过来就行了,如下图所示:




而另一个属性<wsa:Action>则显得比较陌生,还记得通过Http协议访问Web Services时Http Head中的SOAPAction元素吗?

POST /TravelAgentServices/Hotel.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://idior.cnblogs.com/hotel/PlaceOrder"
 
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
  ...
</soap:Envelope>


<wsa:Action>此时的作用与SOAPAction相当,现在的问题就在于这个Action的值从何而来?要想知道答案,首先需要了解<wsa:Action>的作用。假设你在SOAP消息中包含了一个订单,当这个消息达到Service之后,你希望它怎么处理这个订单呢?是为你新增这个订单,还是将这个订单删除,还是更新?同一个消息,Service可能提供了多种处理方法,你希望Service对你所发送的消息如何处理?在消息中指定处理该消息的语义,这就是<wsa:Action>所起的作用。说白了,就是通过<wsa:Action>指定消息到达Service时,究竟触发服务中的哪个方法完成对消息的处理。
知道了<wsa:Action>用于指定将处理该消息的方法,那么不难想象它的值来自于WSDL。
它的构成如下:

[target namespace][delimiter][port type name][delimiter][input|output name]

看了下面的例子就很容易明白了:

<definitions targetNamespace="http://idior.cnblogs.com/resSvr">
  ...
  <portType name="reservationInterface">
     <operation name="opCheckAvailability">
       <input message="tns:checkAvailability" name="CheckAvailability"/>
       <output message="tns:checkAvailabilityResponse" name="Availability"/>
     </operation>
  </portType>
  ...
</definitions>   

[targetNamespace] = http://idior.cnblogs.com/resSvr
[port type name] = reservationInterface
[input name] = CheckAvailability
[output name] = CheckAvailabilityResponse
Applying the pattern above with these values we have:
input action = http://idior.cnblogs.com/resSvr/reservationInterface/CheckAvailability
output action = http://idior.cnblogs.com/resSvr/reservationInterface/CheckAvailabilityResponse


当然一种更简单明了的方法就是在WSDL中直接指定某个方法的输入输出消息的Action,如下所示:

<definitions targetNamespace="http://idior.cnblogs.com/resSvc" ...>
  ...
  <portType name="reservationInterface">
    <operation name="opCheckAvailability">
      <input message="tns:checkAvailability"
        wsa:Action="http://idior.cnblogs.com/resSvc/CheckAvailability"/>
      <output message="tns:checkAvailabilityResponse"
        wsa:Action="http://idior.cnblogs.com/resSvc/CheckAvailabilityResponse"/>
    </operation>
  </portType>
  ...
</definitions>

综合得到Message Addressing Properties中Go类型的属性设定,如下图所示:



从以上介绍的Message Addressing Properties中的属性可以看出,WS-Addressing规范就是把原来处于传输层的寻址信息提升到更高层的消息层面,直接在SOAP消息中包含这些信息,这样就可以摆脱对特定传
输协议的约束,从而使得SOAP消息的传输与具体传输协议无关,这也是Loosely Coupled的体现之一。

     
Tip把底层传输协议的功能提到消息层面再次加以实现,这种方法在WS-*规范中广为采用,比如在以往的中间件系统中并非没有对安全,可靠性以及事务的支持,只不过这种支持依赖于某一特定的实现,这样就失去了通用性,也就无法成为良好的集成方案,当把这些功能放在SOAP消息层面加以实现就可以摆脱这种对底层实现的依赖,而获得更优秀的互操作性。此时,为了避免各持一言,所以才由标准化组织来统一各种功能在消息层面的所作的扩展格式,WS-*也就是在这种情况下出现的。
 

Request- Response Pattern in WS-Addressing

Request-Response 消息交换模式(Message Exchange Pattern)是最经典也是最常用的MEP。在Request-Reply MEP中涉及两个消息-Request Message与Response Message。通常我们使用Http协议访问某个Web Service时,就是采用的这个消息交互模式。不过除了使用Http协议的同步式Request-Response MEP,还有借助诸如TCP,SMTP,MSMQ协议的异步式Request-Response MEP。下面就将分别对Request Message与Response Message中Message Addressing Properties在同步式和异步式下的内容做详细介绍。
 

Request Message
在之前对Message Addressing Properties中Go类型的属性的介绍中,并没有涉及所采用的MEP,其实上述的介绍仍适用于Request-Response MEP,因此不论在Request Message还是Response Message中有关Go类型属性的设定方法都如前所述,只不过它们各自所依据的EndpointReference不同罢了。因此现在重点需要了解在 Request Message中Back类型的属性如何设定。Back类型的属性的值都是EndpointReference类型,其中<wsa:From>则表示发送该Request Message的地址,<wsa:ReplyTo>指定了该Request Message的Response Message将发向的地址,这个值可能与<wsa:From>相同也可能不同。FaultTo则指出当消息处理出现错误时错误消息将去往的地址。在这其中<wsa:ReplyTo>属性是必须的。其实在Http这种同步式Request- Response的MEP中,因为请求和回应都是使用的同一信道,所以并不需要<wsa:ReplyTo>属性,不过为了形式上的统一,WS-Addressing规范还是强制了在Request- Response的MEP下<wsa:ReplyTo>属性不能为空。这样也方便Service辨识Client的MEP,如果ReplyTo有值则是Request-Response,如果没有则是OneWay。对于同步式的Request-Response MEP,你可以采用"http://www.w3.org/2005/08/addressing/anonymous"来设定<wsa:ReplyTo>的值, 如果你另外设定一个EndpointReference, 那么Service会关闭当前的Http连接,利用刚设定的EndpointReference新建一个连接用于发送Response Message。

为了使得在异步情况下,Response Message能够通过<wsa:RelatesTo>属性与Request Message关联上,Request Message中<wsa:MessageID>属性也是必须的。     

      
Note以上都是最新的规范中的内容,在WSE3.0中并没有完全体现,如使用Http协议的Request-Response MEP中ReplyTo属性为空。

下图显示了如何构造Request Message的Message Addressing Properties:




Response Message
Response Message中Go类型的属性的设定来源于Request Message中的<wsa:ReplyTo>属性,<wsa:ReplyTo>的类型也是EndpointReference,因此除了EndpointReference的指向不同,Response Message中Go类型属性的设定与Request Message基本一致,不过需要注意此时的<wsa:Action>属性是采用的WSDL中Output参数的<wsa:Action>值。在采用异步式的Request-Response MEP时,由于Client发出Request Message的和接受Response Message的动作并不处于同一个线程,为了让Client在接受到的Response Message后能够将其与Request Message关联上,此时将使<wsa:RelatesTo>指向Request Message中的<wsa:MessageID>

下图显示了如何构造Response Message的Message Addressing Properties: