频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

可靠的 XML Web Service (2)

来源: 作者: 出处:巧巧读书 2006-09-18 进入讨论组

  标头的作用
在查看代码之前,我们需要了解一下 SOAP 主题,即标头。SOAP 1.1 规范中谈论最少的内容之一就是 SOAP 标头。标头提供了一种扩展消息处理体系结构的简单方法。
SOAP 1.1 规范中提到:标头在实现与消息主体没有特定关系的处理规则(例如验证和事务管理)时非常有用。对任何类型的消息来说,SOAP 标头都是以独立方式对可靠性信息进行编码的完美解决方案。规范中还概述了实施和处理这些标头的标准和规则。

下面我们来看看如何实现包含可靠性信息的 SOAP 标头。首先要为标头确定架构。这很重要,因为它正是最终用户在支持该标头的 Web 服务的 WSDL 文件中看到的实际效果。对于此实现方案,我直接将处理 API 映射到 SOAP 标头。

我来解释一下。在我的处理 API 中有一个名为 ReliabilityInfo 的类。对此类进行实例化时,它将在运行时变成动态对象。也就是说,您可以从可靠性的角度设置确定如何处理出站消息的属性。此对象还可以在运行时序列化为 SOAP 标头。下面是该类及其成员的一个快照。为了清楚起见,我删除了具体的实现和私有成员。

[XMLRootAttribute(ElementName="ReliableHeader", _
   Namespace="http://ericRP/ReliableHeader/2001/", IsNullable=false)]
   public class ReliabilityInfo : SoapHeader
   {      
      public string Destination{}
      public string ConversationId{}
      public int MessageId{}
      public MessageStatus Status{}
      public DateTime SendDate{}
      public DateTime ExpireDate{}
      public string AckURL{}
public enum MessageStatus{}

[XMLIgnore]
      public int MaxRetry{}
      [XMLIgnore]
      public string Text{}
   }

序列化为出站 SOAP 消息时,标头如下所示:

<soap:Header>
<ReliableHeader XMLns="http://ericRP/ReliableHeader/2001/">
<ConversationId>b9e029e1-af0f-42cb-83b0-7888f9e3ffc4</ConversationId>
<MessageId>1</MessageId>
<Status>新</Status>
<SendDate>2001-11-06T14:59:02.1021226-08:00</SendDate>
<ExpireDate>2001-11-06T18:59:02.1021226-08:00</ExpireDate>
<AckURL>http://localhost:8082/ericRPAck/POAck.asmx</AckURL>
</ReliableHeader>
</soap:Header>

这是通过 .NET 框架中两个非常重要的类实现的。基本 XML 序列化块使用 System.XML.Serialization 名称空间类来进行处理。这两个类一个是 XMLRootAttribute 属性类,我使用它告诉序列化程序将文档碎片的根称为 ReliableHeader,并将它与名称空间相关联。此后,所有公共成员也同样会被序列化,除非您告诉序列化程序忽略该成员。我使用的另一个重要名称空间是 System.Web.Services.Protocols。具体地说,即 SoapHeader 类。从该类进行继承时,它会自动将序列化的 XML 加入到 SOAP 消息中。本文稍后将论述如何将标头加入消息。

这非常强大,因为我不仅可以使用类型明确的、编译好的对象作为标头的基础,而且在这些类的成员内部还有特定的实现。

综述
好啦,上面只是对可靠性进行了简单的论述,并阐述了我自己的规范。下面让我们看一看它的代码。

扩展 Web 服务客户端代理
第一步是重新设置现有的 .NET Web 服务客户端代理。记住,此协议可以在任何 SOAP 处理引擎中实现。我选择了 .NET 框架,因为它易于使用、基于标准且可扩展。

选取一个现有的 Web 服务客户端代理(例如 PurchaseOrderProxy),然后添加以下代码:

该类中必须有名为 ReliableHeader 的公共成员,并且其类型必须为 ericRP.ReliabilityInfo。此成员将在运行时通过调用客户端进行设置。稍后将使用此成员为出站消息提供标头信息,并提供在跟踪过程中应用了该标头的消息的状态信息。例如:
public class PurchaseOrderProxy :
      System.Web.Services.Protocols.SoapHttpClientProtocol
   {
      public ReliabilityInfo ReliableHeader;
      
      //为了清楚起见,此处省略了其他代码
   }

在 Web 服务客户端代理中调用的方法必须使用以下属性进行批注:
[SoapHeader("ReliableHeader", Required=true)]

在序列化过程中,此属性将在运行时把适当的标头值加入到出站 SOAP 消息中。此处的 SubmitMessage 方法使用 SoapHeader 属性进行标记。注意,ReliableHeader 是在步骤 1 中实现的成员,而且是必须的。也就是说,如果不在运行时设置此成员,将产生异常。例如:

[SoapHeader("ReliableHeader", Required=true)]
public void SubmitMessage(object message)
{
this.Invoke("SubmitMessage", new object[] {message});      
}
   
在 Web 服务客户端代理中调用的方法必须包含以下属性:
[ericRP.Client.RPClientTrace.TraceExtension()]

此属性表示该方法支持自定义 SOAP 扩展。在消息被序列化之前和之后、且在消息被发送至底层传输机制之前,这种 SOAP 扩展将在运行时被调用。我通常是在消息从客户端计算机发送出去之前,对它进行一些简单的跟踪和记录。稍后再查看此扩展的实现情况。例如:

[ericRP.Client.RPClientTrace.TraceExtension()]
[SoapHeaderAttribute("ReliableHeader", Required=true)]
public void SubmitMessage(object message)
{
this.Invoke("SubmitMessage", new object[] {message});      
}

该类必须从 ericRP.Client.RPClientTrace.IClientTrace 实现。这种接口实现方案提供了基本的跟踪功能,以检查调用程序是否支持特定的跟踪协议。在后面的跟踪功能中可以看到此代码。例如:
public class PurchaseOrderProxy :
   System.Web.Services.Protocols.SoapHttpClientProtocol,
   ericRP.Client.RPClientTrace.IClientTrace
{
public ReliabilityInfo ReliableHeader;
   }

最后,该类必须实现 IClientTrace.GetReliabilityInfo 函数,该函数是 IClientTrace 接口要求的唯一函数。这是一个简单的机制,客户端可以使用它在运行时将消息的状态信息发送到跟踪服务。例如:
public class PurchaseOrderProxy :
   System.Web.Services.Protocols.SoapHttpClientProtocol,
   ericRP.Client.RPClientTrace.IClientTrace
{
public ReliabilityInfo ReliableHeader;

ericRP.ReliabilityInfo ericRP.Client.RPClientTrace.IClientTrace.GetReliabilityInfo()
{      
return ReliableHeader;
}
   }

看起来代码可能很多,但实际上却很简单。事实上,如果时间再多一些,我可以创建从 SoapHttpClientProtocol 继承的新类并明确加以实现,但这种方式对于服务器端来说会更有趣。

扩展 Web 服务服务器存根
下一步,我们来扩展现有的 Web 服务服务器存根。选取一个现有的 .NET Web 服务类(例如 ProcessPurchaseOrder),然后添加以下代码:

该类中必须有一个类型为 ericRP.ReliabilityInfo 的公共成员 ReliableHeader。稍后将使用此成员为入站消息提供反序列化标头信息,并提供在跟踪过程中应用了该标头的消息的状态信息。例如:
public class ProcessPurchaseOrder :
      System.Web.Services.WebService
   {
      public ReliabilityInfo ReliableHeader;
   }

在 Web 服务存根中调用的方法必须使用以下属性进行批注:
[SoapHeader("ReliableHeader", Required=true)]

在反序列化过程中,此属性将在运行时对入站 SOAP 消息中适当的标头值进行反序列化。此处的 SubmitMessage 方法使用 SoapHeader 属性进行标记。例如:

[WebMethod]
[SoapHeader("ReliableHeader", Required=true)]
public void SubmitMessage(object message)
{
//为了清楚起见,此处省略了一些代码   
}

在 Web 服务存根中调用的方法必须使用以下属性进行批注:
[ericRP.S转载保留:http://www.qqread.com/xml-soap/j233976.html 更多文章 更多内容请看XML详解Web开发专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
最新论坛文章
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章