• <ul id="cgeq2"></ul>
  • 歡迎您光臨深圳塔燈網(wǎng)絡(luò)科技有限公司!
    電話圖標(biāo) 余先生:13699882642

    網(wǎng)站百科

    為您解碼網(wǎng)站建設(shè)的點(diǎn)點(diǎn)滴滴

    [WCF REST] 解決資源并發(fā)修改的一個(gè)有效的手段:條件更新(Conditional Update)

    發(fā)表日期:2019-09 文章編輯:小燈 瀏覽次數(shù):2069

    HTTP為條件更新提供了相應(yīng)的報(bào)頭,我們按照分析條件獲取的方式來分析條件更新在HTTP請(qǐng)求/回復(fù)過程中的實(shí)現(xiàn)。客戶端第一次向服務(wù)端發(fā)起針對(duì)某個(gè)資源的請(qǐng)求,服務(wù)端除了將資源數(shù)據(jù)作為回復(fù)消息主體返回之外,會(huì)將與資源關(guān)聯(lián)并且能夠可以用于對(duì)其進(jìn)行對(duì)等性判斷的某個(gè)值作為回復(fù)的ETag報(bào)頭,這與條件獲取時(shí)一致的。

    客戶端通過回復(fù)獲得請(qǐng)求的資源和ETag報(bào)頭值。對(duì)于資源修改操作,客戶端直接針對(duì)獲取的資源進(jìn)行相應(yīng)的修改,并將修改后的資源以HTTP請(qǐng)求的方式向服務(wù)端提交;對(duì)于資源刪除操作,則可以指定被刪除資源的唯一標(biāo)識(shí)直接向服務(wù)端發(fā)送刪除的請(qǐng)求。而之前獲取的ETag指將會(huì)作為請(qǐng)求消息的If-Match報(bào)頭。

    服務(wù)端接收到資源修改/刪除請(qǐng)求后先獲取到現(xiàn)有的資源的ETag值,并將此值與請(qǐng)求消息的If-Match報(bào)頭值進(jìn)行比較。如果兩者不一致,則表明試圖被修改/刪除的資源已經(jīng)被修改了,在這種情況下會(huì)直接回復(fù)一個(gè)HTTP狀態(tài)為“412 (Precondition Failed)”的空消息。條件更新同時(shí)支持針對(duì)PUT、POST和DELETE這三種方法的HTTP請(qǐng)求。

    二、WebOperationContext與條件更新

    服務(wù)端進(jìn)行條件更新檢測(cè),以及客戶端對(duì)If-Match請(qǐng)求報(bào)頭的設(shè)置都可以通過當(dāng)前的WebOperationContext來完成。如下面的代碼片斷所示,表示入棧請(qǐng)求上下文的IncomingWebRequestContext類型具有如下四個(gè)CheckConditionalUpdate方法重載用于進(jìn)行添加更新檢測(cè)。

     1: public class IncomingWebRequestContext
     2: {
     3: //其他成員
     4: public void CheckConditionalUpdate(Guid entityTag);
     5: public void CheckConditionalUpdate(int entityTag);
     6: public void CheckConditionalUpdate(long entityTag);
     7: public void CheckConditionalUpdate(string entityTag);
     8: }

    實(shí)現(xiàn)在CheckConditionalUpdate方法中的條件更新檢測(cè)具有這樣的邏輯:對(duì)于HTTP方法為PUT的請(qǐng)求,如果If-Match報(bào)頭值不為“*”,則直接拋出HTTP狀態(tài)為PreconditionFailed的WebFaultException異常;對(duì)于HTTP方法為POST和DELETE的請(qǐng)求來說,如果If-Match報(bào)頭值為“*”或者包含指定的entityTag則驗(yàn)證通過,否則同樣則直接拋出HTTP狀態(tài)為PreconditionFailed的WebFaultException異常。

    表示出棧請(qǐng)求上下文的OutgoingWebRequestContext類型具有如下一個(gè)IfMatch屬性,客戶端可以通過該屬性對(duì)請(qǐng)求消息的If-Match報(bào)頭進(jìn)行設(shè)置。

     1: public class OutgoingWebRequestContext
     2: {
     3: //其他成員
     4: public string IfMatch { get; set; }
     5: }

    三、實(shí)例演示:通過條件更新解決對(duì)相同資源的并發(fā)修改

    我們同樣通過對(duì)EmployeesService進(jìn)行相應(yīng)的改造來模擬如何通過添加更新實(shí)現(xiàn)對(duì)相同資源的并發(fā)操作問題,這次我們修改的是用于獲取指定ID員工信息的Get操作和用于修改員工信息的Update操作。Get操作在返回與指定員工ID匹配的Employee對(duì)象之前我們將該對(duì)象的哈希碼作為了回復(fù)消息的ETag報(bào)頭(Employee類型重寫了GetHashCode方法)。

     1: public class EmployeesService : IEmployees
     2: {
     3: //其他成員
     4: public Employee Get(string id)
     5: {
     6: Employee employee = employees.FirstOrDefault(e => e.Id == id);
     7: if (null == employee)
     8: {
     9: throw new WebFaultException(HttpStatusCode.NotFound);
    10: }
    11: WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
    12: return employee;
    13: }
    14: public void Update(Employee employee)
    15: {
    16: var existing = employees.FirstOrDefault(e => e.Id == employee.Id);
    17: if (null == existing)
    18: {
    19: throw new WebFaultException(HttpStatusCode.NotFound);
    20: }
    21: //模擬并發(fā)修改
    22: existing.Name += Guid.NewGuid().ToString();
    23:? 
    24: WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode());
    25: employees.Remove(existing);
    26: employees.Add(employee);
    27: WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
    28:? 
    29: }
    30: }

    Update方法中我們通過手工修改相應(yīng)員工的Name屬性的方式來模擬針對(duì)相同員工信息的并發(fā)修改。在真正實(shí)施修改之前調(diào)用當(dāng)前IncomingWebRequestContext的CheckConditionalUpdate方法進(jìn)行條件更新檢測(cè),而作為參數(shù)傳入的ETag值為代表目前員工的Employee對(duì)象的哈希碼。方法的最后我們對(duì)回復(fù)消息的ETag報(bào)頭作了更新。

    我們通過手工創(chuàng)建HTTP請(qǐng)求的方式對(duì)上述的兩個(gè)服務(wù)操作進(jìn)行調(diào)用。如下面的代碼片斷所示,我們首先通過創(chuàng)建的HttpWebRequest對(duì)象調(diào)用Get操作獲得ID為001的員工信息并將其打印出來。然后創(chuàng)建調(diào)用Update操作的HttpWebRequest,并對(duì)HTTP方法(POST)和內(nèi)容類型(application/xml)進(jìn)行了相應(yīng)的設(shè)置。我們之前針對(duì)員工獲取請(qǐng)求得到ETag報(bào)頭和員工數(shù)據(jù)作為本次請(qǐng)求的If-Match報(bào)頭和主體。如果調(diào)用GetResponse方法拋出WebException異常,并且其回復(fù)狀態(tài)為PreconditionFailed,則表明試圖修改的員工信息已被另一個(gè)用戶修改過了,所以我么打印“服務(wù)端數(shù)據(jù)已發(fā)生變化”字樣。

     1: Uri address = new Uri("http://127.0.0.1:3721/employees/001");
     2: var request = (HttpWebRequest)HttpWebRequest.Create(address);
     3: request.Method = "GET";
     4: var response = (HttpWebResponse)request.GetResponse();
     5: string employee;
     6: using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
     7: {
     8: employee = reader.ReadToEnd();
     9: Console.WriteLine("獲取員工信息:");
    10: Console.WriteLine(employee + "\n");
    11: }
    12: try
    13: {
    14: address = new Uri("http://127.0.0.1:3721/employees/");
    15: request = (HttpWebRequest)HttpWebRequest.Create(address);
    16: request.Method = "POST";
    17: request.ContentType = "application/xml";
    18: byte[] buffer = Encoding.UTF8.GetBytes(employee);
    19: request.GetRequestStream().Write(Encoding.UTF8.GetBytes(employee), 0, buffer.Length);
    20: request.Headers.Add(HttpRequestHeader.IfMatch, response.Headers[HttpResponseHeader.ETag]);
    21: Console.WriteLine("修改員工信息:");
    22: request.GetResponse();
    23: }
    24: catch (WebException ex)
    25: {
    26: response = ex.Response as HttpWebResponse;
    27: if (null == response)
    28: {
    29: throw;
    30: }
    31: if (response.StatusCode == HttpStatusCode.PreconditionFailed)
    32: {
    33: Console.WriteLine("服務(wù)端數(shù)據(jù)已發(fā)生變化");
    34: }
    35: else
    36: {
    37: throw;
    38: }
    39: }

    在服務(wù)成功寄宿的情況下調(diào)用這段程序會(huì)在控制臺(tái)上輸出如下的結(jié)果。由于并發(fā)錯(cuò)誤的發(fā)生,員工信息其實(shí)并沒有被真正修改。

     1: 獲取員工信息:
     2: <Employee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Department>開發(fā)部</Department><Grade>G7</Grade><Id>001</Id><Name>張三</Name></Employee>
     3:? 
     4: 修改員工信息:
     5: 服務(wù)端數(shù)據(jù)已發(fā)生變化

    本頁(yè)內(nèi)容由塔燈網(wǎng)絡(luò)科技有限公司通過網(wǎng)絡(luò)收集編輯所得,所有資料僅供用戶學(xué)習(xí)參考,本站不擁有所有權(quán),如您認(rèn)為本網(wǎng)頁(yè)中由涉嫌抄襲的內(nèi)容,請(qǐng)及時(shí)與我們聯(lián)系,并提供相關(guān)證據(jù),工作人員會(huì)在5工作日內(nèi)聯(lián)系您,一經(jīng)查實(shí),本站立刻刪除侵權(quán)內(nèi)容。本文鏈接:http://www.juherenli.com/19703.html
    相關(guān)開發(fā)語言
     八年  行業(yè)經(jīng)驗(yàn)

    多一份參考,總有益處

    聯(lián)系深圳網(wǎng)站公司塔燈網(wǎng)絡(luò),免費(fèi)獲得網(wǎng)站建設(shè)方案及報(bào)價(jià)

    咨詢相關(guān)問題或預(yù)約面談,可以通過以下方式與我們聯(lián)系

    業(yè)務(wù)熱線:余經(jīng)理:13699882642

    Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.    

    • QQ咨詢
    • 在線咨詢
    • 官方微信
    • 聯(lián)系電話
      座機(jī)0755-29185426
      手機(jī)13699882642
    • 預(yù)約上門
    • 返回頂部
    日韩蜜芽精品视频在线观看| 日日夜夜精品免费视频| 国产精品臀控福利在线观看| 亚洲AV成人精品一区二区三区| 国产精品女人在线观看| 精品少妇一区二区三区在线 | 国产成人精品福利色多多| 久久精品一区二区三区中文字幕| 爽爽精品dvd蜜桃成熟时电影院| 亚洲AV无码精品国产成人| 99热这里有免费国产精品| 国产欧美精品123区发布| 中文字幕九七精品乱码| 免费99精品国产自在现线| 中文乱码精品一区二区三区| 久久这里只精品99re66| 99国产精品免费观看视频| 久久青青草原精品影院| 久草热8精品视频在线观看| 久久99热狠狠色精品一区| 精品国产_亚洲人成在线| 午夜不卡久久精品无码免费| 东京热TOKYO综合久久精品| 亚洲精品老司机在线观看| 国产精品高清一区二区人妖| 99精品视频免费观看| 国产精品福利自产拍在线观看| 日本精品一区二区在线播放| 国产毛片片精品天天看视频| 国产成人精品福利网站在线| 嫩B人妻精品一区二区三区| 精品国产一区二区22| caoporn国产精品免费| 一本色道久久88亚洲精品综合| 国产美女久久精品香蕉69| 国产真实乱子伦精品视频| 日日夜夜精品免费视频| 热久久综合这里只有精品电影| 国产欧美精品123区发布| 精品久久久无码人妻字幂| 欧洲精品在线观看|