亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > XML > 正文

可靠的 XML Web Service (2)

2024-09-05 20:55:53
字體:
來源:轉載
供稿:網友
標頭的作用
在查看代碼之前,我們需要了解一下 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.server.rpservertrace.traceextension()]

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

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

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

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

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

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

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

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

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

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

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

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

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;
     }
    }
   }
}

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

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;
   }
}

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

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;
    }
  }
}

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

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

展望
無論是在規范還是在實現方面,xml web service 的未來都是光明的。microsoft 將以協作的、標準驅動的方式工作,確保 xml web service 成為編寫松散耦合的分散式應用程序的最佳體系結構??煽康南⑻幚砗褪聞找幏秾⒃谝院蟀l布。盡管還有大量的實現工作要做,但您現在就可以開始使用 soap 和 wsdl 構建您的框架。與公共規范進程越接近,以后的改動工作就越容易進行。soap 規范就是這種概念的一個顯著例子。世界各地的開發人員都可以跟蹤 soap 規范的發展進程,因此可以毫不費力地對自己的實現方案進行相應地調整。

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



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美尺度大的性做爰视频| 国产欧美 在线欧美| 91免费国产网站| 日韩高清欧美高清| 日韩欧美在线视频免费观看| 日韩在线资源网| 欧美电影免费观看电视剧大全| 久久这里只有精品99| 亚洲一区二区三区xxx视频| 日韩av不卡在线| 456亚洲影院| 亚洲综合精品一区二区| 亚洲综合成人婷婷小说| 日韩精品免费看| 97人人爽人人喊人人模波多| 中文字幕欧美日韩| 国产精品久久久久久中文字| 精品国产31久久久久久| 最近2019年中文视频免费在线观看| 欧美视频国产精品| 日韩免费观看av| 久久国产精品久久久久| 国产日韩中文字幕| 国产精品成人观看视频国产奇米| 狠狠躁18三区二区一区| 国产精品露脸av在线| 欧美大片大片在线播放| 国产日韩中文字幕在线| 日韩福利视频在线观看| 国产亚洲精品久久久优势| 18久久久久久| yellow中文字幕久久| 久久九九全国免费精品观看| 91久久精品一区| 亚洲一级黄色片| 激情久久av一区av二区av三区| 国产精品亚洲视频在线观看| 欧美日韩成人在线播放| 亚洲毛片在线免费观看| 91香蕉嫩草神马影院在线观看| 欧美大片免费观看| 成人黄色午夜影院| 91久久久久久久一区二区| 久久国产精品久久精品| 中文字幕日韩精品在线观看| 日韩免费在线视频| 久久国产精品网站| 国产性猛交xxxx免费看久久| 日本精品性网站在线观看| 91精品久久久久久久| 日韩电影免费在线观看中文字幕| 久久综合久中文字幕青草| 91精品国产成人www| 亚洲人成电影网站色…| 91精品国产色综合久久不卡98| 久久亚洲影音av资源网| 国产精品成人观看视频国产奇米| 久久国内精品一国内精品| 热re91久久精品国99热蜜臀| 亚洲女人天堂成人av在线| 亚洲图片制服诱惑| 日韩最新免费不卡| 国产亚洲激情视频在线| 国产精品午夜视频| 亚洲视频在线观看免费| 91国产视频在线播放| 日韩在线观看成人| 成人a视频在线观看| 日本高清+成人网在线观看| 亚洲福利在线观看| 亚洲人精选亚洲人成在线| 日韩va亚洲va欧洲va国产| 欧美乱大交xxxxx另类电影| 欧美大片免费看| 亚洲第一色在线| 欧美在线视频一区二区| 欧美美最猛性xxxxxx| 日韩精品日韩在线观看| 国产丝袜一区二区三区免费视频| 69视频在线播放| 亚洲第一区第一页| 亚洲日韩中文字幕在线播放| 欧美日韩国产影院| 欧美日韩国产成人高清视频| 久久久免费在线观看| 成人h片在线播放免费网站| 欧美日韩美女在线| 亚洲图片欧美日产| 亚洲欧洲xxxx| 日韩成人在线网站| 亚洲国产精品成人av| 欧美日本亚洲视频| 欧美日韩国产va另类| 91影院在线免费观看视频| 2020欧美日韩在线视频| 青青久久av北条麻妃海外网| 97成人超碰免| 久久久久久这里只有精品| 成人免费福利视频| 欧美激情乱人伦| 91精品国产色综合久久不卡98| 久久夜色撩人精品| 欧美有码在线观看视频| 91亚洲精品在线观看| 国产精品欧美日韩一区二区| 91久久久久久久久| 亚洲最大的免费| 91系列在线观看| 精品国产一区二区三区久久| 国产a∨精品一区二区三区不卡| 国产成人自拍视频在线观看| 欧美另类69精品久久久久9999| 日本久久久久久久久久久| 97精品伊人久久久大香线蕉| 亚洲欧美日韩在线一区| 午夜精品久久久久久久久久久久久| 在线亚洲国产精品网| 中文字幕亚洲情99在线| 成人黄色av播放免费| 高潮白浆女日韩av免费看| 亚洲人成在线观| 国产精品99导航| 精品调教chinesegay| 91影院在线免费观看视频| 欧美精品激情在线| 欧美韩日一区二区| 久久天堂av综合合色| 91色在线观看| 一本大道亚洲视频| 亚洲精品视频在线观看视频| 久久6精品影院| 日韩美女av在线| 日韩成人中文字幕| 欧美极品少妇全裸体| 国产精品福利片| 久久久久久美女| 欧美自拍大量在线观看| 亚洲第一区第一页| 日韩欧美亚洲成人| 国产成人福利夜色影视| 正在播放欧美一区| 日韩精品在线看| 亚洲老板91色精品久久| 欧美怡春院一区二区三区| 亚洲欧美999| 国内精品国产三级国产在线专| 国产欧美精品久久久| 亚洲精品456在线播放狼人| 亚洲美女性视频| 社区色欧美激情 | 日韩国产欧美区| 欧美国产在线视频| 亚洲精品电影网在线观看| 欧美激情一区二区三级高清视频| 欧美色播在线播放| 国内精品久久久久久久| 久久青草精品视频免费观看| 日韩国产高清视频在线| 国产精品黄色影片导航在线观看| 国语自产偷拍精品视频偷| 亚洲人成电影网站色…| 亚洲精品中文字幕av| 国产精品久久久久aaaa九色| 国产精品xxxxx|