WCF SOAP消息剖析
2011-07-22 16:06 田志良 阅读(3762) 评论(3) 编辑 收藏 举报<?xml version='1.0' ?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> <env:Header> </env:Header> <env:Body> </env:Body> </env:Envelope>
消息信封
正如名字的含义一样,消息信封包装消息体和消息头。所有的SOAP消息都有一个消息信封作为根元素。消息信封经常被用来定义不同的贯穿消息的命名空间(和前缀)。这令人对SOAP消息非常兴奋。
消息头
消息头是可以选择的,如果出现的话,必须是消息信封envelope标签的下第一个元素。一个SOAP消息头由一个或多个SOAP消息头块组成。SOAP消息头块包含可以被最终接受者和中介者使用的信息。典型的就是,这些消息头块包含描述消息体数据的信息。换句话说,安全信息,关联或者消息上下文都可以放到消息头部分里。如果需要特定的消息行为,消息头块是必须的。再补充一次,这个想法可以由邮政系统来阐明。如果我想通过邮政系统发送一个信件并且希望在信件到达以后得到一个反馈,我必须填写收信信息并且把它贴到信封上。填写退回地址不会改变信件的内容。它可以改变消息参与者的行为:我必须填写和黏贴退信的信息。邮递员必须所要签名,最终的接受者必须签字接收,邮递员必须返回签收邮件的收据给我(至少是我的邮箱)。
SO消息可以包含相似的信息在消息头里。比如,在我们的订单处理场景里,与路由的确认信息相比,网站或许更想接受消息接受实体的确认信息。这个例子里,网站可以为消息指定一个标识,然后加到请求确认的消息头里。在到达接受者之前,路由需要转发消息到目的习题,然后要求一个确认信息。这个确认信息可以给直接返回给网站或经过路由返回。也可以中介者修改了SOAP消息头或者增加了一个SOAP消息头块。实际上,一个中介者不应该修改消息或者删除消息头,除非消息是发给它的。基于这个模型,就可以轻易的创建一个包含包含路径记录的消息。每个中介者都可以增加它的SOAP消息头,直到消息到达最终的接受者,消息包含一串所有接触这个消息的中介者。如前所述,这个行为是建模在一个真实的邮政系统邮戳或者消息路由的例子上。
消息体
消息体是必须的并且包含消息的有效部分。习惯上,消息体里的数据都是给最终的消息接受者的。不管中间有多少防火墙、路由或者中介者处理了这个SOAP消息。这个不是正式的规定。就像没有规定说邮局不能打开信件一样,同样不能保证一个中介者不打开和改变SOAP消息体。一种可能就是使用数字签名和加密来保证消息从初始发送者到最终接受者的完整性
WCF支持SOAP, REST和 POX(朴素的旧的消息)。大部分目前的WCF应用编程接口(API),是使用SOAP消息结构的。毋庸质疑的是,将来会扩展消息结构,加入新的消息结构,比如JSON。
消息传输
SOAP消息是独立于传输的。换句话说,没必要在消息里添加任何传输规范。这个简单的特性是许多关键特性之一,它使得这个消息结构无比强大。再说一次,用我们的邮政服务例子可以解释。如果一恶搞邮件依赖运输工具,就等于告诉邮递员你邮寄信件的地址,并且不包括信封上的信息。如果我们惯性思考,信件会紧紧地与邮递员绑在一起。这种紧密的耦合不好的几个原因如下:
- 消息可以只能被邮递员投递
- 其它邮政人员不能与消息交互(除非前一个邮递员告诉他)
- 批量分类和投递信件是困难的
- 因为没有信件返回地址,如果信件在处理的时候出现问题,发送者无法被通知。
从面向服务的角度来看,这是一个糟糕的场景。一个更好的计划是它本身应该包含所有相关的地址信息,因此可以避免与传输层的机密耦合。当消息包含这些信息,许多SOAP行为(包括前面提到的行为)是可能的。例如,我们都知道邮件是被邮递员收取、转给分类工具并且通过飞机、火车、轮船或者汽车发送给其他的分类工具和别的邮递员。在我们日常的邮件例子里,可以看到在投递信件的时候运输可以改变(邮递员、分类器、飞机等等),这可以提高效率。如果没有地址的话,那些都不可能。