把"重試"抽象出來做個工具類吧

来源:https://www.cnblogs.com/dingaimin/archive/2020/02/14/12306409.html
-Advertisement-
Play Games

背景介紹 我們在工作中難免會寫一些重覆性的代碼,所以需要我們具備一定的抽象能力,比如把共同的邏輯抽取到抽象類中,也可以通過一些工具類來避免冗餘代碼 今天這篇文章就是把一個調用服務的重試功能抽取出一個工具類,以備復用。這裡為了方便介紹,把調用服務簡化成方法的調用,被調用的 foo 方法如下: ~~~ ...


背景介紹

我們在工作中難免會寫一些重覆性的代碼,所以需要我們具備一定的抽象能力,比如把共同的邏輯抽取到抽象類中,也可以通過一些工具類來避免冗餘代碼

今天這篇文章就是把一個調用服務的重試功能抽取出一個工具類,以備復用。這裡為了方便介紹,把調用服務簡化成方法的調用,被調用的 foo 方法如下:

public static List<String> foo() {// 沒有顯示拋出異常
    System.out.println("調用方法");
        // 模擬拋出異常
    System.out.println(1/0);
    List<String> list = new ArrayList<>();
    list.add("1");
    return list;
}

調用方和重試邏輯如下:

List<String> result = null;
// 重試次數
int retryCount = 0;
// 調用服務的開關,預設打開
boolean callSwitch = true;
// 只要調用服務開關開著,並且重試次數不大於最大的重試次數,就調用服務
while (callSwitch && retryCount <= 3) {
    try {
        // 調用服務
        result = foo();
        // 省略了對結果的校驗,假設到了這裡就說明沒有問題,把調用服務開關關掉
        callSwitch = false;
    } catch (Exception e) {
        // 發生了異常(比如超時,就需要重試了)
        // 調用服務的開關打開
        callSwitch = true;
        retryCount++;
    }
}
// 後面對 result 進行處理

其實上面的代碼就已經解決了,服務重試的邏輯,測試沒有問題後,可以提交代碼讓同事幫忙進行 CR 了,可是小朋同學看到這個代碼後,給了建議:

可以抽象一層,提出一個 retry 的工具類,這樣大家都可以簡單復用你的 retry 邏輯

抽象思考過程

白牙心想,也對哈,那就提出一個工具類吧,可是發了會兒呆,竟然沒有頭緒(反映出了抽象能力的薄弱,平時要多註意抽象能力的培養)。小朋見狀,給了一點提示,白牙立馬在鍵盤上噼里啪啦敲擊了起來,就有了下麵的工具類

主要依賴函數式介面 Supplier 和 BiFunction

public class RetryUtil {
    public static <T> T retry(int maxRetryCount, Supplier<T> supplier, BiFunction<T, Exception, Boolean> consumer) {
        T result = null;
        Exception exception = null;

        int retryCount = 0;
        boolean callMethod = true;
        while (callMethod && retryCount <= maxRetryCount) {
            try {
                // 獲取調用服務的結果
                result = supplier.get();
            } catch (Exception e) {
                // 如果重試次數不小於最大重試次數,就拋出異常,我們把對異常的處理交給業務方
                if (retryCount >= maxRetryCount) {
                    throw e;
                }
                exception = e;  
            }
            // 對結果進行判斷
            callMethod = consumer.apply(result, exception);
            if (callMethod) {
                retryCount++;
            }
        }
        return result;
    }
}

業務調用方的代碼如下:

List<String> result1 = retry(3,// 最大重試次數
                ()-> foo(),// 調用服務
                (list, e) -> e != null || list == null || list.isEmpty());// 對結果處理

自測沒有問題後,又提交代碼讓小朋給 CR 一下,小朋凝視了會兒,就有了下麵的對話

小朋:“retry 方法沒有拋出異常”

白牙:“被調用的服務沒有顯示的拋出異常,這裡也就沒有拋出”

小朋:“那人如果有服務方顯示拋出異常呢?”

白牙:“我再改一版”

服務方顯示拋出了異常,這樣 retry 方法也得顯示拋出異常,但調用方就會顯示會處理的異常,如下所示:

public static List<String> foo() throws Exception{// 顯示拋出異常
    System.out.println("調用方法");
        // 模擬拋出異常
    System.out.println(1/0);
    List<String> list = new ArrayList<>();
    list.add("1");
    return list;
}
public class RetryUtil {
    public static <T> T retry(int maxRetryCount, Supplier<T> supplier, BiFunction<T, Exception, Boolean> consumer) throws Exception{
        // 省略...
}

提示未處理的異常

出現這種情況是因為 Supplier 的 get 方法沒有拋出異常

@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

既然你不支持,那就自己寫個唄,於是就有了下麵的 DspSupplier,它和 Supplier 的主要區別就是在 get 方法中顯示拋出了異常

@FunctionalInterface
interface DspSupplier<T> {
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get() throws Exception;
}

於是 retry 方法就變成了下麵這樣子

public class RetryUtil {
    public static <T> T retry(int maxRetryCount, DspSupplier<T> supplier, BiFunction<T, Exception, Boolean> consumer) throws Exception{
        // 省略...
}

使用了自定義的 Supplier 後,調用方就沒有 “Unhandled exception” 了

總結

我們平時再開發的過程中,可以嘗試去利用函數式介面去實現一些邏輯的抽取,做成一個工具類,供大家使用,簡化人力,也是對自己編碼能力的一個提升。

上面的案例比較簡單,但麻雀雖小,五臟俱全,也是一個不錯的體驗
歡迎關註公眾號 【每天曬白牙】,獲取最新文章,我們一起交流,共同進步!


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

-Advertisement-
Play Games
更多相關文章
  • 在工作中,會遇到需要多線程處理相應的業務需求,最典型的包括Socket的通信。 多線程處理里,就會考慮到,哪個線程先運行,哪個線程後運行的情況。 這裡我介紹一下,使用ManualResetEvent類來對線程進行阻塞和繼續操作。 它有三個重要的方法:Reset、Set和WaitOne。 1、首先介紹 ...
  • RedHat7安裝NetCore環境併發布網站 1.註冊Microsoft簽名密鑰並添加Microsoft產品提要,每台機器只需註冊一次 執行下麵的命令即可 rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsof ...
  • 學習劉鐵猛老師《C#語言入門詳解》視頻,針對其中重點知識點進行總結。 1、什麼是類型? 類型又稱為數據類型(Data Type),數據類型在數據結構中的定義是一個值的集合以及定義在這個值集上的一組操作。 可以簡單理解為數據在記憶體中存儲的“型號”;小記憶體容納大尺寸數據會丟失精準度,發生錯誤;而大記憶體容 ...
  • 在WPF用戶界面中,繪製2D圖形內容的最簡單方法是使用形狀(shape)——專門用於表示簡單的直線、橢圓、矩形以及多變形的一些類。從技術角度看,形狀就是所謂的繪圖圖元(primitive)。可組合這些基本元素來創建更複雜的圖形。 關於WPF中形狀的重要細節是,它們都繼承自FrameworkEleme ...
  • Blend 修改TreeViewItem樣式 1、用Blend for Visual Studio 2019 新建Wpf項目,拖動一個TreeView控制項到Grid上 2、在繪圖視窗選中TreeViewItem,右鍵編輯模版 編輯副本 3、繪製水平、垂直虛線( "參考博文" ) 在TreeViewI ...
  • ASPNetCore 發佈到IIS 準備工作 1.1. 安裝IIS。(具體操作不再說明) 安裝成功後再瀏覽器輸入localhost得到的頁面如下 1.2. 安裝dotnet-hosting-2.2.2-win.exe安裝成功後在IIS 中可以看到如下兩個程式 這兩個程式對應得NetCore的版本不一 ...
  • 1.Ctrl+s:快速保存代碼 一定要記得隨時隨地用 Ctrl+s 來保存我們的代碼哦!!!不然等到電腦關機或者是使用的Eclipse突然閃退就欲哭無淚了。此時腦海裡就突然出現了嗶嗶嗶的畫面~ 2.Alt+/:自動補全代碼或者提示代碼後半部分 牆裂推薦大家使用啊,真的是超級好用了。 給大家舉一個例子 ...
  • 在看 apue 第 19 章偽終端第 6 節使用 pty 程式時,發現“檢查長時間運行程式的輸出”這一部分內容的實際運行結果,與書上所說有出入。 於是展開一番研究,最終發現是書上講的有問題,現在摘出來讓大家評評理。 先上代碼 pty.c pty_fun.c 這是書上標準的 pty 程式,簡單說起來就 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...