特别鸣谢:https://blog.csdn.net/Revivedsun/article/details/53401335
参考方式:以下内容都是demo,直接复制粘贴到项目中即可。
1.自定义手写重试机制
参考地址:https://blog.csdn.net/u010081710/article/details/77879129
参考地址:https://blog.csdn.net/xiaolyuh123/article/details/80209815
/*** 手写重试机制*/
public class MyJavaRetry {public static void main(String[] args) throws InterruptedException {// 重试次数 3 次int maxRryTimes = 3;// 时间间隔 3 秒int intervalTime = 3;// 重试次数int redo = 1;while (redo <= maxRryTimes) {try {doBuinessLogic(redo); // 业务处理,可能需要重试的业务break; //执行成功后直接退出此循环} catch (Exception e) { //异常时,重试次数增加redo++;// 优先使用TimeUnit类中的sleep() 而不是Thread.sleep(4*60*1000);TimeUnit.SECONDS.sleep(intervalTime);continue;}}}private static void doBuinessLogic(int redo) {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");if (redo < 3) {System.err.println("第" + redo + "次执行doBuinessLogic()" + "开始执行时间:" + s.format(new Date()) + "执行失败");throw new RuntimeException();}System.err.println("第" + redo + "次执行doBuinessLogic()" + "开始执行时间:" + s.format(new Date()) + "执行成功");}
}
2.Spring Retry 入门
2.1 maven项目pom.xml
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.2.2.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.2</version></dependency>
2.2 SpringRetryDemo
package com.retry;import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;import org.junit.Test;
import org.springframework.classify.Classifier;
import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.backoff.ExponentialRandomBackOffPolicy;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.backoff.NoBackOffPolicy;
import org.springframework.retry.backoff.Sleeper;
import org.springframework.retry.backoff.UniformRandomBackOffPolicy;
import org.springframework.retry.policy.AlwaysRetryPolicy;
import org.springframework.retry.policy.CompositeRetryPolicy;
import org.springframework.retry.policy.ExceptionClassifierRetryPolicy;
import org.springframework.retry.policy.NeverRetryPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.policy.TimeoutRetryPolicy;
import org.springframework.retry.support.RetryTemplate;/*** spring-retry 版本 1.2.2* * Spring-retry提供了RetryOperations接口的实现类RetryTemplate。* 通过RetryTemplate来完成重试,下面是使用RetryTemplate重试的一些简单例子。* */
public class SpringRetryDemo {private static final int NOTIFY_RETRY_TIMES = 3;/*** 简介:* * Spring-retry提供的RetryOperations接口,该接口提供了若干方法来执行重试操作* * public interface RetryOperations {* <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback) throws E;* * <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback, RecoveryCallback<T> recoveryCallback) throws E;* * <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback, RetryState retryState) throws E, ExhaustedRetryException;* * <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback, RecoveryCallback<T> recoveryCallback, RetryState retryState) throws E;* }* * 调用者通过传入RetryCallback来完成调用者的重试操作。如果callback执行失败(抛出某些异常),那么会按照调用者设定的策略进行重试。* 重试操作直到成功,或根据使用者设定的条件而退出。* * RetryCallback的接口定义如下:* * public interface RetryCallback<T, E extends Throwable> {* * T doWithRetry(RetryContext context) throws E;* }* *//*** TimeoutRetryPolicy策略(注:不是间隔多长时间进行重试的那个时间)* * 代码定义了TimeoutRetryPolicy策略,TimeoutRetryPolicy超时时间默认是1秒。* TimeoutRetryPolicy超时是指在execute方法内部,从open操作开始到调用* TimeoutRetryPolicy的canRetry方法这之间所经过的时间。* 这段时间未超过TimeoutRetryPolicy定义的超时时间,那么执行操作,否则抛出异常。* * protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback, RetryState state) throws E,ExhaustedRetryException {* ……略* RetryContext context = open(retryPolicy, state); * ……略* while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) * // 调用canRetry检查是否可以重试* ……略* }**/@Testpublic void timeoutRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 超时重试策略TimeoutRetryPolicy policy = new TimeoutRetryPolicy();// 超时时间 默认 1000 毫秒policy.setTimeout(2000);// 设置重试策略template.setRetryPolicy(policy);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws InterruptedException {System.out.println("执行Buiness logic");// TODO 对这个策略模式的理解还是模糊 还为理解超时到底是哪个地方超时// 等待3秒TimeUnit.SECONDS.sleep(3);return "SUCCESS";}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** SimpleRetryPolicy 策略* * will execute the callback at least once, and as many as 3 times.* 该策略定义了对指定的异常进行若干次重试。默认情况下,对Exception异常及其子类重试3次.* 如果创建SimpleRetryPolicy并指定重试异常map,可以选择性重试或不进行重试.* */@SuppressWarnings("unused")@Testpublic void simpleRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 简单重试策略 example oneSimpleRetryPolicy policy1 = new SimpleRetryPolicy();// 最大重试次数 默认3次 这里设置为5次policy1.setMaxAttempts(5);// 简单重试策略 example two 1 重试次数5次 2Exception及其子类都进行异重试// Set the max attempts including the initial attempt before retrying// and retry on all exceptions (this is the default):SimpleRetryPolicy policy2 = new SimpleRetryPolicy(5, Collections.singletonMap(Exception.class, true));// 简单重试策略 example threeMap<Class<? extends Throwable>, Boolean> retryableExceptionMaps = new HashMap<Class<? extends Throwable>, Boolean>();;// 空指针异常进行重试 true 进行重试(当Map中的的value为false,那么执行方法,随后抛出异常不进行重试。)retryableExceptionMaps.put(NullPointerException.class, true);SimpleRetryPolicy policy3 = new SimpleRetryPolicy(5, retryableExceptionMaps);// 设置重试策略template.setRetryPolicy(policy1);
// template.setRetryPolicy(policy2);
// template.setRetryPolicy(policy3);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws InterruptedException {if (true) {System.out.println("执行Buiness logic. NPE");// 抛出异常throw new NullPointerException("NullPointerException");}return "SUCCESS";}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** NeverRetryPolicy 策略* * 执行一次待执行操作,若出现异常后不进行重试。* */@Testpublic void neverRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 从不重试策略NeverRetryPolicy policy = new NeverRetryPolicy();// 设置重试策略template.setRetryPolicy(policy);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws InterruptedException {System.out.println("执行Buiness logic. NPE");// 抛出异常throw new NullPointerException("NullPointerException");}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** AlwaysRetryPolicy 策略* * 异常后一直重试直到成功。* */@Testpublic void alwaysRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 一直重试策略AlwaysRetryPolicy policy = new AlwaysRetryPolicy();// 设置重试策略template.setRetryPolicy(policy);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws InterruptedException {System.out.println("执行Buiness logic. NPE");// 抛出异常throw new NullPointerException("NullPointerException");}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** ExceptionClassifierRetryPolicy 策略* * 根据产生的异常选择重试策略。* */@SuppressWarnings("serial")@Testpublic void exceptionClassifierRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();/* setPolicyMap 与 setExceptionClassifier 使用一个即可。*/// 方式 1 setPolicyMap// 根据异常设置重试策略ExceptionClassifierRetryPolicy policy1 = new ExceptionClassifierRetryPolicy();Map<Class<? extends Throwable>, RetryPolicy> policyMap = new HashMap<Class<? extends Throwable>, RetryPolicy>();// 抛出TimeoutException采用AlwaysRetryPolicy策略policyMap.put(TimeoutException.class, new AlwaysRetryPolicy());// 抛出NullPointerException采用NeverRetryPolicy策略policyMap.put(NullPointerException.class, new NeverRetryPolicy());// 异常重试策略mappolicy1.setPolicyMap(policyMap);// 方式 2 setExceptionClassifier// 根据异常设置重试策略ExceptionClassifierRetryPolicy policy2 = new ExceptionClassifierRetryPolicy();// 此外可以通过setExceptionClassifier来为异常指定重试策略。Classifier<Throwable, RetryPolicy> exceptionClassifier = new Classifier<Throwable, RetryPolicy>(){public RetryPolicy classify(Throwable classifiable) {if(classifiable instanceof TimeoutException)return new SimpleRetryPolicy();return new NeverRetryPolicy();}};policy2.setExceptionClassifier(exceptionClassifier);// 设置重试策略template.setRetryPolicy(policy1);
// template.setRetryPolicy(policy2);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE");// 抛出异常throw new NullPointerException("NullPointerException");} else {System.out.println("执行Buiness logic. TE");// 抛出异常throw new TimeoutException("TimeoutException");}}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** CompositeRetryPolicy 策略* * 用户指定一组策略,随后根据optimistic选项来确认如何重试。* * 下面的代码中创建CompositeRetryPolicy策略,并创建了RetryPolicy数组,* 数组有两个具体策略SimpleRetryPolicy与AlwaysRetryPolicy。* * optimistic = true* 当CompositeRetryPolicy设置optimistic为true时,Spring-retry会顺序遍历RetryPolicy[]数组,如果有一个重试策略可重试,* 例如SimpleRetryPolicy没有达到重试次数,那么就会进行重试* * optimistic = false* 如果optimistic选项设置为false。那么有一个重试策略无法重试,那么就不进行重试。* 例如SimpleRetryPolicy达到重试次数不能再重试,而AlwaysRetryPolicy可以重试,那么最终是无法重试的。* * 以下代码,设置setOptimistic(true),而AlwaysRetryPolicy一直可重试,那么最终可以不断进行重试。* */@Testpublic void compositeRetryPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 混合策略CompositeRetryPolicy policy = new CompositeRetryPolicy();// 策略组RetryPolicy[] polices = {new SimpleRetryPolicy(), new AlwaysRetryPolicy()};policy.setPolicies(polices);policy.setOptimistic(true);// 设置重试策略template.setRetryPolicy(policy);try {// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE");// 抛出异常throw new NullPointerException("NullPointerException");} else {System.out.println("执行Buiness logic. TE");// 抛出异常throw new TimeoutException("TimeoutException");}}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});} catch (Exception e) {e.printStackTrace();}}/*** 退避(BackOff)策略* * 当操作执行失败时,根据设置的重试策略进行重试。通过BackoffPolicy可以设定再次重试的时间间隔。* * 接口:* public interface BackOffPolicy {* BackOffContext start(RetryContext context);* void backOff(BackOffContext backOffContext) throws BackOffInterruptedException;* }* * BackOff策略接口的具体实现:* * interface BackOffPolicy* // 实现BackOff接口的抽象类* abstract StatelessBackOffPolicy* class FixedBackOffPolicy // 在等待一段固定的时间后,再进行重试。默认为1秒。* class NoBackOffPolicy // 实现了空方法,因此采用次策略,重试不会等待。这也是RetryTemplate采用的默认退避(backOff)策略* class UniformRandomBackOffPolicy // 均匀随机退避策略,等待时间为 最小退避时间 + [0,最大退避时间 - 最小退避时间)间的一个随机数,如果最大退避时间等于最小退避时间那么等待时间为0。* // 继承BackOff接口的接口* interface SleepingBackOffPolicy* class ExponentialBackOffPolicy // 指数退避策略 ,每次等待时间为 等待时间 = 等待时间 * N ,即每次等待时间为上一次的N倍。如果等待时间超过最大等待时间,那么以后的等待时间为最大等待时间。* // 该类是ExponentialBackOffPolicy的子类* class ExponentialRandomBackOffPolicy // 指数随机策略* class FixedBackOffPolicy // 与StatelessBackoffPolicy的同名实现类返回等待时间的方法是一致的。而两者的主要区别是,SleepingbackOffPolicy可以设置用户定义的Sleeper。* class UniformRandomBackOffPolicy // 与StatelessBackoffPolicy的同名实现类返回等待时间的方法是一致的。而两者的主要区别是,SleepingbackOffPolicy可以设置用户定义的Sleeper。**//*** 实现BackOff接口的抽象类* StatelessBackoffPolicy 抽象类下的退避策略* */@SuppressWarnings("unused")@Testpublic void statelessBackoffPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 简单重试策略SimpleRetryPolicy policy = new SimpleRetryPolicy(); // 默认重试3次// 设置重试策略template.setRetryPolicy(policy);// 1. 固定退避策略FixedBackOffPolicy backOffPolicy1 = new FixedBackOffPolicy();backOffPolicy1.setBackOffPeriod(2000); // Default back off period - 1000ms.// 2. 默认退避策略 不等待,直接重试NoBackOffPolicy backOffPolicy2 = new NoBackOffPolicy();// 3. 均匀随机退避策略 UniformRandomBackOffPolicy backOffPolicy3 = new UniformRandomBackOffPolicy();// 等待时间为 最小退避时间 + [0, 最大退避时间 - 最小退避时间)间的一个随机数 (如果最大退避时间等于最小退避时间那么等待时间为0)backOffPolicy3.setMinBackOffPeriod(2000); // Default min back off period - 500ms.backOffPolicy3.setMaxBackOffPeriod(5000); // Default max back off period - 1500ms.// 设置退避策略template.setBackOffPolicy(backOffPolicy1);
// template.setBackOffPolicy(backOffPolicy2);
// template.setBackOffPolicy(backOffPolicy3);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new NullPointerException("NullPointerException");} else {System.out.println("执行Buiness logic. TE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new TimeoutException("TimeoutException");}}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** 继承BackOff接口的接口* SleepingbackOffPolicy 接口下的退避策略* */@SuppressWarnings("serial")@Testpublic void sleepingbackOffPolicyTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 简单重试策略SimpleRetryPolicy policy = new SimpleRetryPolicy();// 重试5次policy.setMaxAttempts(5);// 设置重试策略template.setRetryPolicy(policy);// 1. 指数退避策略ExponentialBackOffPolicy backOffPolicy1 = new ExponentialBackOffPolicy();// 每次等待时间为 等待时间 = 等待时间 * N ,即每次等待时间为上一次的N倍。 (如果等待时间超过最大等待时间,那么以后的等待时间为最大等待时间。)// 以下设置 初始时间间隔为2000毫秒,N = 3,¸最大间隔为6000毫秒,那么从第3次重试开始,以后每次等待时间都为6000毫秒。backOffPolicy1.setInitialInterval(2000);// 等待时间 The default 'initialInterval' value - 100 millisecs.backOffPolicy1.setMultiplier(3);// 等待倍数 The default 'multiplier' value - value 2 (100% increase per backoff).backOffPolicy1.setMaxInterval(6000);//最大等待时间 The default maximum backoff time (30 seconds).// 2. 指数随机退避策略ExponentialRandomBackOffPolicy backOffPolicy2 = new ExponentialRandomBackOffPolicy();// 算法是 等待时间 = 等待时间 * (1 + Random(随机数) * (N - 1))backOffPolicy2.setInitialInterval(2000);// 等待时间 The default 'initialInterval' value - 100 millisecs.backOffPolicy2.setMultiplier(3);// 等待倍数 The default 'multiplier' value - value 2 (100% increase per backoff).// 3. 固定退避策略FixedBackOffPolicy backOffPolicy3 = new FixedBackOffPolicy();backOffPolicy3.setBackOffPeriod(2000); // Default back off period - 1000ms.// 用户自定义 sleeper 不知道能干啥 不懂Sleeper sleeper3 = new Sleeper() {@Overridepublic void sleep(long backOffPeriod) throws InterruptedException {// 不理解这个的作用TimeUnit.SECONDS.sleep(10);System.out.println("sleeper");}};backOffPolicy3.setSleeper(sleeper3);// 4. 均匀随机退避策略 UniformRandomBackOffPolicy backOffPolicy4 = new UniformRandomBackOffPolicy();// 等待时间为 最小退避时间 + [0, 最大退避时间 - 最小退避时间)间的一个随机数 (如果最大退避时间等于最小退避时间那么等待时间为0)backOffPolicy4.setMinBackOffPeriod(2000); // Default min back off period - 500ms.backOffPolicy4.setMaxBackOffPeriod(5000); // Default max back off period - 1500ms.// 用户自定义 sleeper 不知道能干啥 不懂Sleeper sleeper4 = new Sleeper() {@Overridepublic void sleep(long backOffPeriod) throws InterruptedException {// 不理解这个的作用TimeUnit.SECONDS.sleep(10);System.out.println("sleeper");}};backOffPolicy4.setSleeper(sleeper4);// 设置退避策略template.setBackOffPolicy(backOffPolicy1);
// template.setBackOffPolicy(backOffPolicy2);
// template.setBackOffPolicy(backOffPolicy3);
// template.setBackOffPolicy(backOffPolicy4);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new NullPointerException("NullPointerException");} else {System.out.println("执行Buiness logic. TE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new TimeoutException("TimeoutException");}}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "failed callback";}});System.out.println(result);}/*** 监听器* */@Testpublic void retryListenerTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 简单重试策略SimpleRetryPolicy policy = new SimpleRetryPolicy(); // 默认重试3次// 设置重试策略template.setRetryPolicy(policy);// 固定时间退避策略FixedBackOffPolicy backOffPolicy1 = new FixedBackOffPolicy();backOffPolicy1.setBackOffPeriod(2000); // Default back off period - 1000ms.// 设置退避策略template.setBackOffPolicy(backOffPolicy1);/*** * 上述代码注册了两个Listener,Listener中的三个实现方法,onError, open, close会在执行重试操作时被调用,* 在RetryTemplate中doOpenInterceptors, doCloseInterceptors, doOnErrorInterceptors* 会调用监听器对应的open, close, onError 方法。** doOpenInterceptors方法在第一次重试之前会被调用,如果该方法返回true,则会继续向下直接,如果返回false,则抛出异常,停止重试。* * doOnErrorInterceptors 在抛出异常后执行,* * doCloseInterceptors 会在重试操作执行完毕后调用。* */// 监听器1RetryListener retryListener1 = new RetryListener() {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("1-open");return true;}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {System.out.println("1-onError");}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {System.out.println("1-close");}};// 监听器1RetryListener retryListener2 = new RetryListener() {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("2-open");return true;}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {System.out.println("2-onError");}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {System.out.println("2-close");}};// 监听组RetryListener[] listeners = {retryListener1, retryListener2};/** 设置监听器 当注册多个Listener时,open方法按会按Listener的注册顺序调用,* 而onError和close则按Listener注册的顺序逆序调用。* * open 初始重试调用* onError 发生异常就调用* close 重试次数全部结束调用*/template.setListeners(listeners);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new NullPointerException("NullPointerException");} else {System.out.println("执行Buiness logic. TE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new TimeoutException("TimeoutException");}}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {// TODO 推送次数,推送完毕后,还没有成功,发送预警短信,通知人工处理return "FAIL";}});System.out.println(result);}@Testpublic void realRetryListenerTest() throws Exception{// Spring-retry提供了RetryOperations接口的实现类RetryTemplateRetryTemplate template = new RetryTemplate();// 简单重试策略SimpleRetryPolicy policy = new SimpleRetryPolicy(); // 默认重试3次// 设置重试策略template.setRetryPolicy(policy);// 固定时间退避策略FixedBackOffPolicy backOffPolicy1 = new FixedBackOffPolicy();backOffPolicy1.setBackOffPeriod(2000); // Default back off period - 1000ms.// 设置退避策略template.setBackOffPolicy(backOffPolicy1);// 监听器1RetryListener retryListener1 = new RetryListener() {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("1-open");return true;}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {System.out.println("1-onError");System.out.println("save FAIL notify info");}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {if (context.getRetryCount() < NOTIFY_RETRY_TIMES) {// TODO 表示没有到达重试次数 就成功了。在这儿入库,保存通知成功信息。System.out.println("save SUCCESS notify info");}System.out.println("1-close" + "重试了" + context.getRetryCount() +"次");}};// 监听组RetryListener[] listeners = {retryListener1};template.setListeners(listeners);// 执行String result = template.execute(new RetryCallback<String, Exception>() {public String doWithRetry(RetryContext context) throws Exception {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");int number = new Random().nextInt(10) + 1;if (number > 5) {System.out.println("执行Buiness logic. NPE" + "开始执行时间:" + s.format(new Date()));// 抛出异常throw new NullPointerException("NullPointerException");}return "SUCCESS";}},// 当重试执行完闭,操作还未成为,那么可以通过RecoveryCallback完成一些失败事后处理。new RecoveryCallback<String>() {public String recover(RetryContext context) throws Exception {return "FAIL";}});System.out.println(result);}
}
tips:如有疑问,欢迎评论交流。