封裝guava重試神器

一:引入guava依賴
com.github.rholder -> guava-retrying 2.0.0-AONE-SNAPSHOT
二:封裝調(diào)用工具類

package common.utils.guava;

import com.github.rholder.retry.*;
import com.google.common.base.Predicates;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * @mhh
 * guava重試工具
 * @param <T>
 */
public class GuavaRetryer<T> {

    private Retryer<T> retryer;

    public GuavaRetryer(){

    }
    /**
     * 初始化重試實(shí)例
     * @param sleepTime  重試間隔時(shí)間,單位:秒
     * @param retryTimes 失敗重試次數(shù)
     * @param callerName 調(diào)用接口名稱
     */
    public GuavaRetryer(Integer sleepTime, Integer retryTimes,String callerName,String dingTalkToken){
        retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()                                 //拋出runtime異常质和、checked異常時(shí)都會重試,但是拋出error不會重試。
                .retryIfResult(Predicates.equalTo(null))    //返回null也需要重試
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重調(diào)策略
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //嘗試次數(shù)
                .withRetryListener(new MyRetryListener(callerName,dingTalkToken))
                .build();
    }

    /**
     * 初始化重試實(shí)例
     * @param sleepTime  重試間隔時(shí)間,單位:秒
     * @param retryTimes 失敗重試次數(shù)
     * @param retryListener 重試監(jiān)聽實(shí)例
     */
    public GuavaRetryer(Integer sleepTime, Integer retryTimes, RetryListener retryListener){
        retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()                                 //拋出runtime異常明刷、checked異常時(shí)都會重試,但是拋出error不會重試檐嚣。
                .retryIfResult(Predicates.equalTo(null))    //返回null也需要重試
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重調(diào)策略
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //嘗試次數(shù)
                .withRetryListener(retryListener)
                .build();
    }


    /**
     * 執(zhí)行可重試方法
     * @param callable
     * @return
     * @throws Exception
     */
    public T executeWithRetry(Callable<T> callable) throws Exception {
        if(retryer == null){
            throw new Exception("未初始化重試參數(shù)糊肤!");
        }
        T result= retryer.call(callable);
        return result;
    }

    /**
     * 執(zhí)行可重試方法
     * @param callable
     * @return
     * @throws Exception
     */
    public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
                              String callerName,String dingTalkToken) throws Exception {
        retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()                                 //拋出runtime異常琴昆、checked異常時(shí)都會重試,但是拋出error不會重試馆揉。
                .retryIfResult(Predicates.equalTo(null))    //返回null也需要重試
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重調(diào)策略
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //嘗試次數(shù)
                .withRetryListener(new MyRetryListener(callerName,dingTalkToken))
                .build();
        T result= retryer.call(callable);
        return result;
    }

    /**
     * 執(zhí)行可重試方法
     * @param callable
     * @return
     * @throws Exception
     */
    public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
                              MyRetryListener myRetryListener) throws Exception {
        retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()                                 //拋出runtime異常业舍、checked異常時(shí)都會重試,但是拋出error不會重試升酣。
                .retryIfResult(Predicates.equalTo(null))    //返回null也需要重試
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重調(diào)策略
                .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //嘗試次數(shù)
                .withRetryListener(myRetryListener)
                .build();
        T result= retryer.call(callable);
        return result;
    }



}

三:封裝回調(diào)監(jiān)聽器

package common.utils.guava;
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener;
import common.helper.DingTalkHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class MyRetryListener implements RetryListener {

    private final static Logger LOGGER = LoggerFactory.getLogger(MyRetryListener.class);

    private String callerName;

    private String dingTalkToken;

    public MyRetryListener(){
    }

    public MyRetryListener(String callerName,String dingTalkToken){
        this.callerName = callerName;
        this.dingTalkToken = dingTalkToken;
    }

    @Override
    public <T> void onRetry(Attempt<T> attempt) {
        Long attempNumber = attempt.getAttemptNumber();
        Long delay = attempt.getDelaySinceFirstAttempt();
        Boolean hasException = attempt.hasException();
        Boolean hasResult =  attempt.hasResult();

        String msg = String.format("重試接口:%s,重試次數(shù)=%s,距離第一次重試的延遲=%s,是否有異常=%s,是否有返回結(jié)果=%s",
                callerName,attempNumber,delay,hasException,hasResult);
        LOGGER.info(msg);

        if (attempt.hasException()) {
            String causeBy = attempt.getExceptionCause().toString();
            String errorMsg = String.format("重試接口:%s,異常原因=%s",callerName,causeBy);
            String title = "外部接口重試調(diào)用監(jiān)控";
            String sendMsg = msg + "\n" + errorMsg;
            LOGGER.error(errorMsg);
            DingTalkHelper.sendMarkdownMsg(dingTalkToken, title, sendMsg);
        }
    }
}

四:使用例子

package common.utils.guava;

import com.github.rholder.retry.Attempt;

public class RetryTester {

    public static void main(String[] arg) throws Exception {
        /*GuavaRetryer<String> guavaRetryer = new GuavaRetryer(3,3,"測試接口");
        String result1 = guavaRetryer.executeWithRetry(() -> {
            String obj = "測試調(diào)用重試接口失敗";
            throw new Exception(obj);
            //return obj;
        });*/
        GuavaRetryer<String> guavaRetryer = new GuavaRetryer();
        /*String result2 = guavaRetryer.executeWithRetry(3,3,"測試接口",() -> {
            Thread.sleep(2000);
            String obj = "測試調(diào)用重試接口失敗";
            throw new Exception(obj);
            //return obj;
        });*/
        String result3 = guavaRetryer.executeWithRetry(3,3,() -> {
            Thread.sleep(2000);
            String obj = "測試調(diào)用重試接口失敗";
            throw new Exception(obj);
            //return obj;
        },new MyRetryListener(){
            @Override
            public <T> void onRetry(Attempt<T> attempt) {
                Long attempNumber = attempt.getAttemptNumber();
                Long delay = attempt.getDelaySinceFirstAttempt();
                Boolean hasException = attempt.hasException();
                Boolean hasResult =  attempt.hasResult();
                System.out.println("重試結(jié)果:"+attempNumber+","+delay+","+hasException+","+hasResult);
            }
        });


    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舷暮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子噩茄,更是在濱河造成了極大的恐慌下面,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绩聘,死亡現(xiàn)場離奇詭異沥割,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凿菩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門机杜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衅谷,你說我怎么就攤上這事椒拗。” “怎么了获黔?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵蚀苛,是天一觀的道長。 經(jīng)常有香客問我玷氏,道長堵未,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任预茄,我火速辦了婚禮兴溜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘耻陕。我一直安慰自己,他們只是感情好刨沦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布诗宣。 她就那樣靜靜地躺著,像睡著了一般想诅。 火紅的嫁衣襯著肌膚如雪召庞。 梳的紋絲不亂的頭發(fā)上岛心,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機(jī)與錄音篮灼,去河邊找鬼忘古。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诅诱,可吹牛的內(nèi)容都是我干的髓堪。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼娘荡,長吁一口氣:“原來是場噩夢啊……” “哼干旁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起炮沐,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤争群,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后大年,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體换薄,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年翔试,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轻要。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遏餐,死狀恐怖伦腐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情失都,我是刑警寧澤柏蘑,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站粹庞,受9級特大地震影響咳焚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庞溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一革半、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧流码,春花似錦又官、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驾荣,卻和暖如春外构,著一層夾襖步出監(jiān)牢的瞬間普泡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工审编, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撼班,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓垒酬,卻偏偏與公主長得像砰嘁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子伤溉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350