.net Core數據的幕等性

来源:https://www.cnblogs.com/chenxi001/archive/2019/10/13/11668541.html
-Advertisement-
Play Games

一、背景 代碼實例:https://gitee.com/D_C_L/CurtainEtcAOP.git我們實際系統中有很多操作,是不管做多少次,都應該產生一樣的效果或返回一樣的結果。 例如: 1. 前端重覆提交選中的數據,應該後臺只產生對應這個數據的一個反應結果。 2. 我們發起一筆付款請求,應該只 ...


一、背景 

代碼實例:https://gitee.com/D_C_L/CurtainEtcAOP.git
我們實際系統中有很多操作,是不管做多少次,都應該產生一樣的效果或返回一樣的結果。 
例如:
 

1. 前端重覆提交選中的數據,應該後臺只產生對應這個數據的一個反應結果。 
2. 我們發起一筆付款請求,應該只扣用戶賬戶一次錢,當遇到網路重發或系統bug重發,也應該只扣一次錢; 
3. 發送消息,也應該只發一次,同樣的簡訊發給用戶,用戶會哭的; 
4. 創建業務訂單,一次業務請求只能創建一個,創建多個就會出大問題。 

等等很多重要的情況,這些邏輯都需要冪等的特性來支持。 

二、冪等性概念
 
冪等(idempotent、idempotence)是一個數學與電腦學概念,常見於抽象代數中。 

在編程中.一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函數,或冪等方法,是指可以使用相同參數重覆執行,並能獲得相同結果的函數。這些函數不會影響系統狀態,也不用擔心重覆執行會對系統造成改變。例如,“getUsername()和setTrue()”函數就是一個冪等函數. 

更複雜的操作冪等保證是利用唯一交易號(流水號)實現. 

我的理解:冪等就是一個操作,不論執行多少次,產生的效果和返回的結果都是一樣的 

一,正式開始了

現在我們們要做一個點擊按鈕之後等待後臺返回之後才可以再次請求方法,其他的重覆請求直接進行攔截

在這裡我使用攔截器進行實現(也可以使用中間件來實現),主要就是以AOP(切麵編程是面向對象的優化),將一些緊密的業務進行切開,在中間進行自己的一些邏輯處理

主要的實現思路就是使用toekn+Redis緩存進行(當我們訪問某個方法的時候給用戶的客戶端存取一個cookie)cookie裡面主要是存的toekn,當我們訪問介面的時候一定要帶上有效的

token才能訪問方法或者控制器。

客戶端訪問方法的時候存token到Redis裡面,當請求方法的時候帶上token,攔截器裡面判斷是不是存放在Redis裡面的token如果不是的直接攔截返回,如果帶上的是有效的token刪除舊token

生成一個新的token存放在cookie裡面,存到Redis,給第二次請求發放token。

代碼理解:

 

//視圖頁面
    public partial class HomeController : Controller
    {
        private readonly RedisHelp cache = new RedisHelp();
        /// <summary>
        /// 首頁  獲取token
        /// </summary>
        /// <returns></returns>
        [NoSign]
        public IActionResult Index()
        {
            string token = Guid.NewGuid().ToString();
            HttpContext.Response.Cookies.Append("token", token);
            cache.SetValue("token", token);
            return View();
        }
    }

 

當瀏覽器訪問這個視圖的時候給他發放一個token。

這裡存在cooke的好處就是,下一次請求會直接帶上上一次發放的Toekn,我們在前臺就不需要去做任何操作了,這樣攔截器才能算上是一個獨立的模塊。

我們需要訪問這個介面,保證同時點擊的時候只能有一次

 /// <summary>
    /// 介面控制器
    /// </summary>
    public partial class HomeController : Controller
    {
        /// <summary>
        /// 接受提交請求
        /// </summary>
        /// <returns></returns>
        public JsonResult Submit()
        {
            ResponseJson responseJson = new ResponseJson();
            responseJson.msg = "更新了token";
            return Json(responseJson);
        }
    }

下麵就是攔截器的代碼

    /// <summary>
    /// 適合全局的
    /// </summary>
    public class SignFilter : ActionFilterAttribute
    {
        private RedisHelp cache = new RedisHelp();
        /// <summary>
        /// 請求之前
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // 判斷是否檢查登陸
            var noNeedCheck = false;
            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                noNeedCheck = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
                  .Any(a => a.GetType().Equals(typeof(NoSignAttribute)));
            }
            if (noNeedCheck)return;

            ResponseJson responseJson = new ResponseJson();
            var token = context.HttpContext.Request.Cookies["token"];
            #region 判斷數據有效性
            if (string.IsNullOrWhiteSpace(token))
            {
                responseJson.msg = "toekn不能空";
                context.Result = new JsonResult(responseJson);
                return;
            } else if (cache.GetValue("token") ==null) {
                responseJson.msg = "toekn不能空";
                context.Result = new JsonResult(responseJson);
                return;
            } else if (!cache.DeleteKey("token")) {
                responseJson.msg = "token已不存在";
                context.Result = new JsonResult(responseJson);
                return;
            }
            #endregion
            base.OnActionExecuting(context);
        }

        /// <summary>
        /// 請求過了之後,在去分發token
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            //隨機值
            string redisToken = Guid.NewGuid().ToString() + new Random().Next(100000, 99999999);
            context.HttpContext.Response.Cookies.Append("token", redisToken);
            //初使化並設置Cookie的名稱
            cache.SetValue("token", redisToken);
        }
    }

    /// <summary>
    /// 不需要登陸的地方加個特性
    /// </summary>
    public class NoSignAttribute : ActionFilterAttribute { }

 

 

 

 

 

但是這個只適合於個人在點擊的時候的,下次我分享一下多人的模式。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 場景 Winform控制項-DevExpress18下載安裝註冊以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100061243 DevExpress的TreeList怎樣設置數據源,從實例入手: https:/ ...
  • 場景 Winform控制項-DevExpress18下載安裝註冊以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100061243 在上面已經實現DevExpress的安裝之後,拖拽一個TreeList,然後怎樣給 ...
  • 前言: 通過Fiddler抓取瀏覽器請求數據,相信大家已經都會用了,我們知道Fiddler是通過在本機計算器添加一個預設的代理伺服器來實現的抓包數據的,埠號為:8888。 其實當我們打開Fiddler的設置也可以看到: 然後查看本地計算器的網路代理設置: 基於上面的原理,Fiddler就實現了經過 ...
  • 在項目視圖中,找到-》輸出 視窗,在視窗中選擇ASP.NET Core Web伺服器,調試項目即可看到執行的sql語句 ...
  • 點這裡進入ABP進階教程目錄 我們嘗試在新增/編輯界面增加一個下拉框用來代替輸入框編輯Status 添加實體 打開領域層(即JD.CRS.Core)的Entitys目錄 //用以存放實體對象添加一個類StatusCode.cs //狀態信息 更新模型 更新查詢視圖模型 打開展示層(即JD.CRS.W ...
  • 點這裡進入ABP進階教程目錄 在功能按鈕區增加一個自定義按鈕 - Add(創建課程) 添加按鈕 打開展示層(即JD.CRS.Web.Mvc)的\wwwroot\view-resources\Views\Course\Index.js //用以存放Course查詢相關腳本 自帶按鈕已有五個我們再添加一 ...
  • 簡述 我們做軟體工作的雖然每天都離不開網路,可網路協議細節卻不是每個人都會接觸和深入瞭解。我今天就來和大家一起學習下Socket,並寫一個簡單的聊天程式。 一些基礎類 首先我們每天打開瀏覽器訪問網頁信息都是使用的HTTP/HTTPS協議,而HTTP是通過的TCP建立的連接。TCP底層又是通過的Soc ...
  • 關鍵字:流程未來節點處理人 工作流快速開發平臺 工作流流設計 業務流程管理 asp.net 開源工作流 業務背景:一個流程在啟動起來後,是可以對一些節點計算出來處理人是誰,流程的走向。對於另外一些節點處理人有可能需要相關的人員調整的。在一些審批的環境下,需要把能夠計算出來的節點處理人在發起時計算出來... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...