Java編寫自定義重試工具類的示例代碼
Java重試工具類,零依賴。可配置項(xiàng):接受的異常類型、返回值校驗(yàn)、最大重試次數(shù)、重試間隔時(shí)間。
1 重試工具類 RetryUtils源碼
RetryUtils:
使用了lombok的@Slf4j注解用于打印日志,不用可移除。
import com.example.exception.RetryException;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* <h2>重試工具類</h2>
*
* @author GFire
* @since 2025/4/22 17:58
*/
@Slf4j
public abstract class RetryUtils {
/**
* 失敗重試
*
* @param task 執(zhí)行的任務(wù),無(wú)返回值
* @param acceptException 可接受的異常類型,執(zhí)行的任務(wù)拋出此異常(及其子類)則失敗重試。null表示不接受任何異常
* @param maxRetryCount 最大重試次數(shù)
* @param waitTime 重試間隔等待時(shí)間, 單位毫秒, <=0則不等待
* @throws RetryException 如果任務(wù)重試超過(guò)最大次數(shù)、或拋出不可接受的異常,則統(tǒng)一包裝拋出RetryException
*/
public static void doWithRetry(Runnable task, Class<? extends Throwable> acceptException, int maxRetryCount, int waitTime) {
if (task == null) {
throw new IllegalArgumentException("task can not be null");
}
doWithRetry(() -> {
task.run();
return 1;
}, i -> i == 1, acceptException, maxRetryCount, waitTime);
}
/**
* 失敗重試
*
* @param task 執(zhí)行的任務(wù),有返回值
* @param isValid 判斷任務(wù)返回值是否合法,不合法則失敗重試
* @param acceptException 可接受的異常類型,執(zhí)行的任務(wù)拋出此異常(及其子類)則失敗重試。null表示不接受任何異常
* @param maxRetryCount 最大重試次數(shù)
* @param waitTime 重試間隔等待時(shí)間, 單位毫秒, <=0則不等待
* @return supplier執(zhí)行結(jié)果
* @throws RetryException 如果任務(wù)重試超過(guò)最大次數(shù)、或拋出不可接受的異常,則統(tǒng)一包裝拋出RetryException
*/
public static <T> T doWithRetry(Supplier<T> task, Predicate<T> isValid, Class<? extends Throwable> acceptException, int maxRetryCount, int waitTime) {
if (task == null) {
throw new IllegalArgumentException("task can not be null");
}
if (isValid == null) {
throw new IllegalArgumentException("isValid can not be null");
}
if (maxRetryCount <= 0) {
throw new IllegalArgumentException("maxRetryCount must be > 0");
}
T result = null;
for (int tryCount = 1; tryCount <= maxRetryCount; tryCount++) {
try {
result = task.get();
if (isValid.test(result)) {
return result;
} else {
log.error("result invalid, tryCount: {}, result: {}", tryCount, result);
}
} catch (Throwable e) {
handleException(e, acceptException, maxRetryCount, tryCount);
}
if (waitTime > 0 && tryCount < maxRetryCount) {
sleep(waitTime); // 等待一段時(shí)間后重試
}
}
throw new RetryException("result: " + result);
}
private static void handleException(Throwable e, Class<? extends Throwable> acceptException, int maxRetryCount, int tryCount) {
log.error("error, tryCount: {}, Exception: ", tryCount, e);
if (acceptException != null && acceptException.isInstance(e)) {
if (tryCount == maxRetryCount) { // 最后一次重試仍失敗,則拋出
throw new RetryException(e);
}
} else { // 不可接受的異常,直接拋出
throw new RetryException(e);
}
}
private static void sleep(int waitTime) {
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RetryException(e);
}
}
}
RetryException:
/**
* <h2>重試異常</h2>
*
* @author GFire
* @since 2025/4/23 11:20
*/
public class RetryException extends RuntimeException {
public RetryException(String message) {
super(message);
}
public RetryException(Throwable cause) {
super(cause);
}
}
2 使用方式
示例1:任務(wù)無(wú)返回值
// 模擬調(diào)用API接口,失敗重試 RetryUtils.doWithRetry(() -> apiService.query(), Exception.class, 3, 2000);
解釋:任務(wù)apiService.query()無(wú)返回值、接受Exception異常、最大重試次數(shù)為3、重試間隔2秒
示例2:任務(wù)有返回值、需校驗(yàn)返回值
/**
* 模擬發(fā)送通知
*/
public boolean send(String content) {
try {
RetryUtils.doWithRetry(() -> noticeService.send(content), this::isValid, Exception.class, 3, 2000);
return true;
} catch (RetryException e) {
log.error("send error: {}", e.toString());
}
return false;
}
private boolean isValid(String res) {
if (StringUtils.isNotEmpty(res)) {
JSONObject response = JSON.parseObject(res);
return "ok".equals(response.getString("status"));
}
return false;
}
解釋:任務(wù)noticeService.send(content)有String類型的返回值、isValid方法判斷返回值是否合法、接受Exception異常、最大重試次數(shù)為3、重試間隔2秒
示例3:任務(wù)有返回值、無(wú)需校驗(yàn)返回值
RetryUtils.doWithRetry(() -> noticeService.send(), (res) -> true, Exception.class, 3, 2000);
解釋:任務(wù)noticeService.send()有String類型的返回值、(res) -> true認(rèn)為任意返回值都合法(即無(wú)校驗(yàn))、接受Exception異常、最大重試次數(shù)為3、重試間隔2秒
到此這篇關(guān)于Java編寫自定義重試工具類的示例代碼的文章就介紹到這了,更多相關(guān)Java自定義重試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Web開發(fā)項(xiàng)目中中文亂碼解決方法匯總
這篇文章主要為大家詳細(xì)匯總了Java Web開發(fā)項(xiàng)目中中文亂碼的解決方法,分析了5種Java Web中文亂碼情況,感興趣的小伙伴們可以參考一下2016-05-05
springboot啟動(dòng)時(shí)運(yùn)行代碼詳解
在本篇內(nèi)容中我們給大家整理了關(guān)于在springboot啟動(dòng)時(shí)運(yùn)行代碼的詳細(xì)圖文步驟以及需要注意的地方講解,有興趣的朋友們學(xué)習(xí)下。2019-06-06
Spring Security 構(gòu)建rest服務(wù)實(shí)現(xiàn)rememberme 記住我功能
這篇文章主要介紹了Spring Security 構(gòu)建rest服務(wù)實(shí)現(xiàn)rememberme 記住我功能,需要的朋友可以參考下2018-03-03
Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之樹
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之樹,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java數(shù)據(jù)結(jié)構(gòu)的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-05-05
EL表達(dá)式的隱式對(duì)象_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了EL表達(dá)式的隱式對(duì)象,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
idea環(huán)境下Maven無(wú)法正常下載pom中配置的包問(wèn)題
這篇文章主要介紹了idea環(huán)境下Maven無(wú)法正常下載pom中配置的包的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
Java手寫簡(jiǎn)易版HashMap的使用(存儲(chǔ)+查找)
這篇文章主要介紹了Java手寫簡(jiǎn)易版HashMap的使用(存儲(chǔ)+查找),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Java利用Spire.XLS for Java自動(dòng)化設(shè)置Excel的文檔屬性
一個(gè)專業(yè)的 Excel 文件,其文檔屬性往往能大大提升文件的可管理性和可檢索性,下面我們就來(lái)看看Java如何使用Spire.XLS for Java實(shí)現(xiàn)自動(dòng)化設(shè)置Excel的文檔屬性吧2025-12-12

