麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發(fā) > XML > 正文

可靠的 XML Web Service (2)

2024-09-05 20:55:53
字體:
供稿:網(wǎng)友
標頭的作用
在查看代碼之前,我們需要了解一下 soap 主題,即標頭。soap 1.1 規(guī)范中談論最少的內(nèi)容之一就是 soap 標頭。標頭提供了一種擴展消息處理體系結(jié)構(gòu)的簡單方法。soap 1.1 規(guī)范中提到:標頭在實現(xiàn)與消息主體沒有特定關(guān)系的處理規(guī)則(例如驗證和事務管理)時非常有用。對任何類型的消息來說,soap 標頭都是以獨立方式對可靠性信息進行編碼的完美解決方案。規(guī)范中還概述了實施和處理這些標頭的標準和規(guī)則。

下面我們來看看如何實現(xiàn)包含可靠性信息的 soap 標頭。首先要為標頭確定架構(gòu)。這很重要,因為它正是最終用戶在支持該標頭的 web 服務的 wsdl 文件中看到的實際效果。對于此實現(xiàn)方案,我直接將處理 api 映射到 soap 標頭。

我來解釋一下。在我的處理 api 中有一個名為 reliabilityinfo 的類。對此類進行實例化時,它將在運行時變成動態(tài)對象。也就是說,您可以從可靠性的角度設(shè)置確定如何處理出站消息的屬性。此對象還可以在運行時序列化為 soap 標頭。下面是該類及其成員的一個快照。為了清楚起見,我刪除了具體的實現(xiàn)和私有成員。

[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 框架中兩個非常重要的類實現(xiàn)的。基本 xml 序列化塊使用 system.xml.serialization 名稱空間類來進行處理。這兩個類一個是 xmlrootattribute 屬性類,我使用它告訴序列化程序?qū)⑽臋n碎片的根稱為 reliableheader,并將它與名稱空間相關(guān)聯(lián)。此后,所有公共成員也同樣會被序列化,除非您告訴序列化程序忽略該成員。我使用的另一個重要名稱空間是 system.web.services.protocols。具體地說,即 soapheader 類。從該類進行繼承時,它會自動將序列化的 xml 加入到 soap 消息中。本文稍后將論述如何將標頭加入消息。

這非常強大,因為我不僅可以使用類型明確的、編譯好的對象作為標頭的基礎(chǔ),而且在這些類的成員內(nèi)部還有特定的實現(xiàn)。

綜述
好啦,上面只是對可靠性進行了簡單的論述,并闡述了我自己的規(guī)范。下面讓我們看一看它的代碼。

擴展 web 服務客戶端代理
第一步是重新設(shè)置現(xiàn)有的 .net web 服務客戶端代理。記住,此協(xié)議可以在任何 soap 處理引擎中實現(xiàn)。我選擇了 .net 框架,因為它易于使用、基于標準且可擴展。

選取一個現(xiàn)有的 web 服務客戶端代理(例如 purchaseorderproxy),然后添加以下代碼:

該類中必須有名為 reliableheader 的公共成員,并且其類型必須為 ericrp.reliabilityinfo。此成員將在運行時通過調(diào)用客戶端進行設(shè)置。稍后將使用此成員為出站消息提供標頭信息,并提供在跟蹤過程中應用了該標頭的消息的狀態(tài)信息。例如:
public class purchaseorderproxy :
      system.web.services.protocols.soaphttpclientprotocol
   {
      public reliabilityinfo reliableheader;
      
      //為了清楚起見,此處省略了其他代碼
   }

在 web 服務客戶端代理中調(diào)用的方法必須使用以下屬性進行批注:
[soapheader("reliableheader", required=true)]

在序列化過程中,此屬性將在運行時把適當?shù)臉祟^值加入到出站 soap 消息中。此處的 submitmessage 方法使用 soapheader 屬性進行標記。注意,reliableheader 是在步驟 1 中實現(xiàn)的成員,而且是必須的。也就是說,如果不在運行時設(shè)置此成員,將產(chǎn)生異常。例如:

[soapheader("reliableheader", required=true)]
public void submitmessage(object message)
{
this.invoke("submitmessage", new object[] {message});      
}
   
在 web 服務客戶端代理中調(diào)用的方法必須包含以下屬性:
[ericrp.client.rpclienttrace.traceextension()]

此屬性表示該方法支持自定義 soap 擴展。在消息被序列化之前和之后、且在消息被發(fā)送至底層傳輸機制之前,這種 soap 擴展將在運行時被調(diào)用。我通常是在消息從客戶端計算機發(fā)送出去之前,對它進行一些簡單的跟蹤和記錄。稍后再查看此擴展的實現(xiàn)情況。例如:

[ericrp.client.rpclienttrace.traceextension()]
[soapheaderattribute("reliableheader", required=true)]
public void submitmessage(object message)
{
this.invoke("submitmessage", new object[] {message});      
}

該類必須從 ericrp.client.rpclienttrace.iclienttrace 實現(xiàn)。這種接口實現(xiàn)方案提供了基本的跟蹤功能,以檢查調(diào)用程序是否支持特定的跟蹤協(xié)議。在后面的跟蹤功能中可以看到此代碼。例如:
public class purchaseorderproxy :
   system.web.services.protocols.soaphttpclientprotocol,
   ericrp.client.rpclienttrace.iclienttrace
{
public reliabilityinfo reliableheader;
   }

最后,該類必須實現(xiàn) iclienttrace.getreliabilityinfo 函數(shù),該函數(shù)是 iclienttrace 接口要求的唯一函數(shù)。這是一個簡單的機制,客戶端可以使用它在運行時將消息的狀態(tài)信息發(fā)送到跟蹤服務。例如:
public class purchaseorderproxy :
   system.web.services.protocols.soaphttpclientprotocol,
   ericrp.client.rpclienttrace.iclienttrace
{
public reliabilityinfo reliableheader;

ericrp.reliabilityinfo ericrp.client.rpclienttrace.iclienttrace.getreliabilityinfo()
{      
return reliableheader;
}
   }

看起來代碼可能很多,但實際上卻很簡單。事實上,如果時間再多一些,我可以創(chuàng)建從 soaphttpclientprotocol 繼承的新類并明確加以實現(xiàn),但這種方式對于服務器端來說會更有趣。

擴展 web 服務服務器存根
下一步,我們來擴展現(xiàn)有的 web 服務服務器存根。選取一個現(xiàn)有的 .net web 服務類(例如 processpurchaseorder),然后添加以下代碼:

該類中必須有一個類型為 ericrp.reliabilityinfo 的公共成員 reliableheader。稍后將使用此成員為入站消息提供反序列化標頭信息,并提供在跟蹤過程中應用了該標頭的消息的狀態(tài)信息。例如:
public class processpurchaseorder :
      system.web.services.webservice
   {
      public reliabilityinfo reliableheader;
   }

在 web 服務存根中調(diào)用的方法必須使用以下屬性進行批注:
[soapheader("reliableheader", required=true)]

在反序列化過程中,此屬性將在運行時對入站 soap 消息中適當?shù)臉祟^值進行反序列化。此處的 submitmessage 方法使用 soapheader 屬性進行標記。例如:

[webmethod]
[soapheader("reliableheader", required=true)]
public void submitmessage(object message)
{
//為了清楚起見,此處省略了一些代碼   
}

在 web 服務存根中調(diào)用的方法必須使用以下屬性進行批注:
[ericrp.server.rpservertrace.traceextension()]

此屬性表示該方法支持自定義 soap 擴展。稍后再查看此擴展的實現(xiàn)情況。

注意:此擴展與客戶端擴展不同。
例如:

[soapheader("reliableheader", required=true)]
[ericrp.server.rpservertrace.traceextension()]
public void submitmessage(object message)
{
//為了清楚起見,此處省略了一些代碼   
}

在 web 服務存根中調(diào)用的方法必須使用以下屬性進行批注:
[soapdocumentmethod(oneway=true)]

此屬性表示被調(diào)用的函數(shù)不返回值。更具體地說,即一旦消息被反序列化,此屬性就會強制 web 服務向客戶端返回 http 202 響應。對于分離消息的最終處理來說,這不失為一個有效的機制,否則,客戶端就不得不同步地等待服務返回響應。例如:

[webmethod]
[soapdocumentmethod(oneway=true)]
[soapheader("reliableheader", required=true)]
[ericrp.server.rpservertrace.traceextension()]
public void submitmessage(object message)
{
//為了清楚起見,此處省略了一些代碼   
}

該類必須從 ericrp.server.rpservertrace.iservertrace 實現(xiàn)。這種接口實現(xiàn)方案提供了基本的跟蹤功能,以檢查調(diào)用程序是否支持特定的跟蹤協(xié)議。在后面的跟蹤功能中可以看到此代碼。例如:
public class processpurchaseorder :
system.web.services.webservice, ericrp.server.rpservertrace.iservertrace
   {
      public reliabilityinfo reliableheader;
   }

最后,該類必須實現(xiàn) iservertrace.getreliabilityinfo 函數(shù)。這是 iservertrace 接口要求的唯一函數(shù)。例如:
public class processpurchaseorder :
system.web.services.webservice, ericrp.server.rpservertrace.iservertrace
   {
      public reliabilityinfo reliableheader;

ericrp.reliabilityinfo ericrp.server.rpservertrace.iservertrace.getreliabilityinfo()
      {   
         return reliableheader;
      }
   }

好啦,現(xiàn)有的 web 服務客戶端和服務器已準備就緒。下面我們來看看 soapextension 是如何工作的。

查看 rpclienttrance 和 rpservertrace
為了實現(xiàn)可靠性處理,我決定使用 soapextension。soapextension 是一個可繼承的基類,使用它可以跟蹤 soap 消息的出站序列化和入站反序列化。正是在這個跟蹤過程中,對消息進行記錄并檢查其狀態(tài)。記得前面講過,web 服務客戶端代理方法實現(xiàn) [ericrp.client.rpclienttrace.traceextension()]。當調(diào)用該方法時,此屬性將在 soap 消息出站序列化時調(diào)用以下代碼。

需要特別指出的主要函數(shù)是 processmessage。發(fā)送出站消息時,processmessage 將提供有關(guān)該消息序列化之前和之后的全部狀態(tài)信息。這時,將檢查誰在調(diào)用并將 client 屬性的類級別成員與當前消息分離。然后檢查消息是否處于 afterserialize 狀態(tài)。如果已經(jīng)序列化,則可以在消息被發(fā)送至服務器之前進行記錄。通過名為 processoutgoingmessagetext 的自定義函數(shù),首先進行一些流交換以免破壞底層消息流。然后檢查客戶端是否支持 iclienttrace 接口。如果客戶端支持該接口,則表明它們也支持可靠性協(xié)議。通過接口檢查功能,可以調(diào)用 getreliabilityinfo 以便將當前消息返回可應用于該消息的 conversationmanager,然后設(shè)置一些屬性并調(diào)用 logmessage。logmessage 將當前消息信息寫入本地數(shù)據(jù)庫,然后發(fā)送事件,通知客戶端已記錄該消息。

public class rpclienttrace : soapextension
{      
public override void processmessage(soapmessage message)
{
  soapclientmessage tmpmsg = (soapclientmessage)message;
  _client = tmpmsg.client;

  if (message.stage == soapmessagestage.afterserialize)
  {
    processoutgoingmessagetext(message);
  }
}

  public void processoutgoingmessagetext(soapmessage message)
  {
   newstream.position = 0;
   textreader reader = new streamreader(newstream);
   stringbuilder strmessage = new stringbuilder();
   strmessage.append(reader.readtoend());
   newstream.position = 0;
   copy(newstream, oldstream);

   if(_client is client.rpclienttrace.iclienttrace)
   {
    try
    {
client.rpclienttrace.iclienttrace _ptrclient = _
   (client.rpclienttrace.iclienttrace)_client;
   reliabilityinfo rinfo = _ptrclient.getreliabilityinfo();
      rinfo.text = strmessage.tostring();
      rinfo.destination = message.url;
   rinfo.manager.logmessage(rinfo);
     }
     catch(exception e)
     {
      throw e;
     }
    }
   }
}

服務器端的情況有點復雜,因為服務器需要為入站消息執(zhí)行額外的操作。被調(diào)用的 web 方法用于實現(xiàn) [ericrp.server.rpservertrace.traceextension()]。以下代碼將在入站消息反序列化之前和之后被調(diào)用:

public class rpservertrace : soapextension
{
public override void processmessage(soapmessage message)
{
try
{
  switch (message.stage)
  {
   case soapmessagestage.beforedeserialize:
        readincomingmessagetext(message);
    break;
   case soapmessagestage.afterdeserialize:
     soapservermessage tmpmsg = (soapservermessage)message;
     _server = tmpmsg.server;
     if(_server is server.rpservertrace.iservertrace)
     {
          server.rpservertrace.iservertrace _ptrserver = _
             (server.rpservertrace.iservertrace)_server;
     reliabilityinfo rinfo = _ptrserver.getreliabilityinfo();
   ericrp.reliabilityinfo tempinfo = (ericrp.reliabilityinfo)message.headers[0];
   tempinfo.text = _tempmessage;
   server.conversationmanager manager = new server.conversationmanager();
   manager.processmessage(tempinfo);

     }
   break;
   }
}

進行流交換和接口檢查后,將在服務器對話管理器上調(diào)用 processinboundmessage。processinboundmessage 用于檢查核心消息的狀態(tài)。消息限制程序即在此使用。首先檢查消息是否過期,然后檢查其是否重復,最后檢查其是否有序。如果滿足所有三個條件,則將記錄該消息并向客戶端發(fā)送確認;如果不能滿足任一條件,則將更改消息的狀態(tài)并向客戶端發(fā)送確認。

public void processinboundmessage(ericrp.reliabilityinfo rinfo)
{         
    try
    {
   if(isexpired(rinfo))
   {
   rinfo.status = ericrp.reliabilityinfo.messagestatus.expired;
   sendack(rinfo);
   }
   else if(isdulplicate(rinfo))
   {
   rinfo.status = ericrp.reliabilityinfo.messagestatus.duplicate;
   sendack(rinfo);
   }
   else if(isnotordered(rinfo))
   {
   rinfo.status = ericrp.reliabilityinfo.messagestatus.notordered;
   sendack(rinfo);
   }
   else
{
   rinfo.status = ericrp.reliabilityinfo.messagestatus.success;
   logmessage(rinfo);
   sendack(rinfo);
   }
    }
    catch(exception e)
    {
   throw e;
    }
  }
}

要使本示例在生產(chǎn)環(huán)境中可行,還需要做大量的實施工作。更重要的是,api 應當基于一個以后將會發(fā)布的公共標準。本文的主要目的就是引發(fā)讀者思考問題,了解一下 .net 框架中的主要 web 服務類,我想這兩個目的都已經(jīng)達到。如果您正在尋求可靠異步消息處理的成熟可用的實現(xiàn)方案,建議您看一看 microsoft biztalk™ server 2000。

最后,您可以使用類似的跟蹤功能執(zhí)行所有類型的操作,例如加密、客戶分配和通知。記住,這項附加的功能增加了 web 服務所需的處理基礎(chǔ)結(jié)構(gòu)。

展望
無論是在規(guī)范還是在實現(xiàn)方面,xml web service 的未來都是光明的。microsoft 將以協(xié)作的、標準驅(qū)動的方式工作,確保 xml web service 成為編寫松散耦合的分散式應用程序的最佳體系結(jié)構(gòu)。可靠的消息處理和事務規(guī)范將在以后發(fā)布。盡管還有大量的實現(xiàn)工作要做,但您現(xiàn)在就可以開始使用 soap 和 wsdl 構(gòu)建您的框架。與公共規(guī)范進程越接近,以后的改動工作就越容易進行。soap 規(guī)范就是這種概念的一個顯著例子。世界各地的開發(fā)人員都可以跟蹤 soap 規(guī)范的發(fā)展進程,因此可以毫不費力地對自己的實現(xiàn)方案進行相應地調(diào)整。

希望我能有一個水晶球,為您準確地描繪未來 xml web service 的基礎(chǔ)結(jié)構(gòu);希望我們目前依賴的所有公用服務,例如安全性、事務、存儲、查詢、路由、進程協(xié)調(diào)等等,將來都能夠直接映射至 web 服務體系結(jié)構(gòu);而且 gxa 實現(xiàn)方案可以滲透到核心開發(fā)語言、應用程序框架、業(yè)務處理框架和企業(yè)基礎(chǔ)結(jié)構(gòu)中。到那時,我們就能夠真正地以無縫方式將任意兩種服務耦合在一起。但愿 ericrp 不會真的成為服務背后的可靠性層。<微笑>



發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 片在线观看 | 毛片在哪看| 毛片免费在线视频 | 黄色片在线免费播放 | 欧美日韩色 | 国产精品久久久免费观看 | 日本黄色一级视频 | 久久情爱网 | 国产精品一区在线观看 | 午夜视频色 | 欧美aⅴ视频 | 一级毛片在线免费观看视频 | 国产乱淫av片免费 | 午夜精品一区二区三区免费 | 成人在线观看地址 | 亚洲精品3| 免费一级a毛片在线播放视 日日草夜夜操 | 国内成人自拍视频 | 全网免费毛片 | 欧美黄色大片免费观看 | 欧美 日韩 国产 成人 | 一级在线视频 | 亚洲成人免费影视 | 国产精品久久久久久久久久东京 | 99riav视频一区二区 | 欧洲精品视频在线观看 | 欧美精品一区自拍a毛片在线视频 | 欧美女优一区 | 国产精品91久久久 | 青青青在线免费 | 日韩av在线网址 | 黑人日比视频 | 久久久久久久久久久国产精品 | 国产亚洲精品久久 | 久久精品99久久久久久2456 | 精品一二三区视频 | 亚洲九九色 | 国产在线精品一区二区三区 | 精品在线观看一区 | 亚洲一级簧片 | 狠狠干最新网址 |