一:引入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);
}
});
}
}