使用场景:业务中经常遇到需要重试机制对一段代码进行 多次执行常遇到的有 访问网络数据接口,由于网络等原因需要重试 两到多次,直到返回正确结果为止。
已有方案:
1. guava-retrying 开源项目
<dependency> <groupId>com.github.rholder</groupId> <artifactId>guava-retrying</artifactId> <version>2.0.0</version> </dependency>2. spring-retry
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>以上两种方案都可以完美的解决 重试问题
但是上面两种方案都略显臃肿,需要依赖第三方项目(主要是没大看懂他们的源码),基于Java8 函数式编程(太香了)
开发一下工具Demo (只是个Demo,一种方案,可优化,求分享)
上代码:
package com.barton; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Supplier; /** * create by barton on 2020-6-30 */ public class RetryTest { /** * 重试机制 * @param retryNumber 重试次数 * @param waitTime 重试等待时间 * @param retryIfExceptionType 重试一场类型 * @param call 执行主体 * @param retryIf 重试条件 * @param <T> * @return T */ public static <T> T retry( Integer retryNumber, Long waitTime, Class<? extends Throwable> retryIfExceptionType, Supplier<T> call, BiFunction<Integer,T,Boolean> retryIf ){ T result = null; Integer currentNumber = 1; Boolean exceptionFlag = false; while (true){ if(currentNumber > retryNumber){ return result; } exceptionFlag = false; try{ result = call.get(); }catch (Exception e){ if(retryIfExceptionType != null && e.getClass().getName().equals(retryIfExceptionType.getName())){ exceptionFlag = true; } e.printStackTrace(); } if(exceptionFlag){ currentNumber++; continue; } if(retryIf != null){ Boolean isRetry = retryIf.apply(currentNumber,result); // true 重试,false 不重试返回 if(!isRetry){ return result; }else { //间隔一定时间重试 if(waitTime != null && waitTime > 0){ try { TimeUnit.MILLISECONDS.sleep(waitTime); } catch (InterruptedException e) { e.printStackTrace(); } } } } currentNumber++; } } public static void main(String[] args) { String res = retry(3, 2000L, NumberFormatException.class, ()->{ // 执行主体 System.out.println("do something"); return "SUCCESS"; },(number,result)->{ System.out.println("retry:"+number); // 判断是否需要重试,根据业务修改 if("SUCCESS".equals(result)){ return true; }else{ return false; } }); System.out.println(res); } }(注:只是个Demo ,需要使用的同学可优化,欢迎分享)