java 重试_Java重试机制修改
最近無意間看到了一段代碼,實話實說看的我有點難受,剛開始的時候還略微有點懵,只是感覺代碼很長。等我捋了一遍之后,發現是一段調用遠程接口,失敗進行重試功能的代碼。代碼如下:
image.png
方法用到了遞歸,在重試次數小于零跳出。
說一下存在的問題吧:
接口重試和業務本身不發生關系,所以具有很高的耦合性
方法采用遞歸實現,有棧溢出的風險
重試邏輯無法進行重用
可配置性比較低
看下怎么改一下:
-抽離出重試代碼,預留接口,業務代碼填入,抽離工具類如下:
public abstract class MyRetryTemplate {
//重試次數
private int retryTime;
//重試時間
private int sleepTime;
//是否倍數增長
private boolean multiple = false;
/**
* 執行業務方法邏輯,由實現類實現
*
* @return
*/
public abstract T remote() throws Exception;
public T execute() throws InterruptedException {
for (int i = 1; i < retryTime + 1; i++) {
try {
return remote();
} catch (Exception e) {
System.out.println(e.getMessage());
if (multiple){
Thread.sleep(sleepTime);
}
else{
Thread.sleep(sleepTime * (i));
}
}
}
return null;
}
public T submit(ExecutorService executorService) {
Future submit = executorService.submit((Callable) () -> execute());
try {
return (T) submit.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
public MyRetryTemplate setRetryTime(int retryTime) {
this.retryTime = retryTime;
return this;
}
public MyRetryTemplate setSleepTime(int sleepTime) {
this.sleepTime = sleepTime;
return this;
}
public MyRetryTemplate setMultiple(boolean multiple) {
this.multiple = multiple;
return this;
}
}
上面的類中,值定義了重試的次數,間隔的時間,和時間的增長參數,預留了remote()抽象方法,交由具體的實現類來實現。類中使用了泛型,支持返回不同的對象。并且支持同步和異步調用。
看下修改后的代碼,如下:
image.png
是不是感覺一下清爽了很多,這里重試相關的參數,我直接寫死在了代碼中,可以通過配置文件和數據庫配置引入。這個方法應該還能精簡,最后兩句感覺還是有點多余,由于不知道是干啥的, 就暫且留在這吧。
修改后的代碼,雖然解決了一些上面的問題,但是并沒有完全解決,代碼的侵入性,上面已經說了既然這是重試的邏輯,就不應該出現在代碼中。有沒有解決的辦法呢,有,切面。
下面看下通過切面該怎么實現。
首先定義一個注解:
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
int count() default 0 ;
long sleep() default 0 ;
}
定義切面
@Aspect
@Component
public class RetryAspect {
ExecutorService executorService = Executors.newFixedThreadPool(3);
@Around(value = "@annotation(Retry)")
public Object execute(ProceedingJoinPoint point, Retry retry) throws InterruptedException {
System.out.println("----------------- Aspect ---------------------");
MyRetryTemplate myRetryTemplate = new MyRetryTemplate() {
@Override
public ParametersHolder remote() throws Throwable {
return (ParametersHolder) point.proceed();
}
}.setRetryTime(3).setSleepTime(10000).submit(executorService);
return submit;
}
}
最終實現:
image.png
在注解中,添加自定義的參數,便可以實現零侵入,也更容易實現方法的復用,如果有其他的業務需要實現重試,直接在業務方法上添加注解即可。
如果不想用這種方法,也可以借助第三方工具guava-retrying和 spring-retry 來實現此功能。
總結
以上是生活随笔為你收集整理的java 重试_Java重试机制修改的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java自动部署maven_Maven+
- 下一篇: python导入urllib reque