spring-retry使用介绍

2年前 (2022) 程序员胖胖胖虎阿
228 0 0

文章目录

  • 系列文章目录
    • Springboot集成Netty
    • Springboot集成Rabbitmq
    • Springboot集成Retry
    • springboot集成websocket
    • Springboot集成Redis
    • springboot整合rabbitmq使用示例
  • 前言
  • 一、spring-retry是什么?
  • 二、使用步骤
    • 1.引入maven库
    • 2. 在spring启动类上开启重试功能
    • 2.公共业务代码
    • 3. 以往的重试做法
    • 4. 使用spring-retry的命令式编码
      • 4.1 定义重试监听器
      • 4.2 定义重试配置
      • 4.3 命令式编码
    • 5 使用spring-retry的注解式编码
    • 6 启动打印效果
  • 三、总结
  • 四、示例源码

系列文章目录

Springboot集成Netty

Springboot集成Rabbitmq

Springboot集成Retry

springboot集成websocket

Springboot集成Redis

springboot整合rabbitmq使用示例


前言

以往我们在进行网络请求的时候,需要考虑网络异常的情况,本文就介绍了利用spring-retry框架进行网络异常重试的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、spring-retry是什么?

是spring提供的一个重试框架,原本自己实现的重试机制,现在spring帮封装好提供更加好的编码体验。

二、使用步骤

1.引入maven库

代码如下(示例):

	<dependency>
	    <groupId>org.springframework.retry</groupId>
	    <artifactId>spring-retry</artifactId>
	</dependency>
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-aspects</artifactId>
	    <version>4.3.9.RELEASE</version>
	</dependency>

2. 在spring启动类上开启重试功能

提示:添加@EnableRetry注解开启

@SpringBootApplication
@EnableRetry
public class SpringRetryDemoApplication {
    public static SpringRetryAnnotationService springRetryAnnotationService;
    public static SpringRetryImperativeService springRetryImperativeService;
    public static TranditionalRetryService tranditionalRetryService;

    @Autowired
    public void setSpringRetryAnnotationService(SpringRetryAnnotationService springRetryAnnotationService) {
        SpringRetryDemoApplication.springRetryAnnotationService = springRetryAnnotationService;
    }

    @Autowired
    public void setSpringRetryImperativeService(SpringRetryImperativeService springRetryImperativeService) {
        SpringRetryDemoApplication.springRetryImperativeService = springRetryImperativeService;
    }

    @Autowired
    public void setTranditionalRetryService(TranditionalRetryService tranditionalRetryService) {
        SpringRetryDemoApplication.tranditionalRetryService = tranditionalRetryService;
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringRetryDemoApplication.class, args);
        springRetryAnnotationService.test();
        springRetryImperativeService.test();
        tranditionalRetryService.test();
    }

}

2.公共业务代码

@Service
@Slf4j
public class CommonService {
    public void test(String before) {
        for (int i = 0; i < 10; i++) {
            if (i == 2) {
                log.error("{}:有异常哦,我再试多几次看下还有没异常", before);
                throw new RuntimeException();
            }
            log.info("{}:打印次数: {}", before, i + 1);
        }
    }

    public void recover(String before) {
        log.error("{}:还是有异常,程序有bug哦", before);
    }
}

3. 以往的重试做法

@Service
@Slf4j
public class TranditionalRetryService {
    @Autowired
    CommonService commonService;

    public void test() {
        // 定义重试次数以及重试时间间隔
        int retryCount = 3;
        int retryTimeInterval = 3;
        for (int r = 0; r < retryCount; r++) {
            try {
                commonService.test("以前的做法");
            } catch (RuntimeException e) {
                if (r == retryCount - 1) {
                    commonService.recover("以前的做法");
                    return;
                }
                try {
                    Thread.sleep(retryTimeInterval * 1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }

        }

    }
}

4. 使用spring-retry的命令式编码

4.1 定义重试监听器

提示:监听重试过程的生命周期

@Slf4j
public class MyRetryListener extends RetryListenerSupport {
    @Override
    public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("监听到重试过程关闭了");
        log.info("=======================================================================");
    }

    @Override
    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("监听到重试过程错误了");
    }

    @Override
    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
        log.info("=======================================================================");
        log.info("监听到重试过程开启了");
        return true;
    }

}

4.2 定义重试配置

提示:配置RetryTemplate重试模板类

@Configuration
public class RetryConfig {
    @Bean
    public RetryTemplate retryTemplate() {
        // 定义简易重试策略,最大重试次数为3次,重试间隔为3s
        RetryTemplate retryTemplate = RetryTemplate.builder()
                .maxAttempts(3)
                .fixedBackoff(3000)
                .retryOn(RuntimeException.class)
                .build();
        retryTemplate.registerListener(new MyRetryListener());
        return retryTemplate;
    }

}

4.3 命令式编码

@Service
@Slf4j
public class SpringRetryImperativeService {
    @Autowired
    RetryTemplate retryTemplate;
    @Autowired
    CommonService commonService;

    public void test() {
        retryTemplate.execute(
                retry -> {
                    commonService.test("命令式");
                    return null;
                },
                recovery -> {
                    commonService.recover("命令式");
                    return null;
                }
        );
    }
}

5 使用spring-retry的注解式编码

@Service
@Slf4j
public class SpringRetryAnnotationService {
    @Autowired
    CommonService commonService;

    /**
     * 如果失败,定义重试3次,重试间隔为3s,指定恢复名称,指定监听器
     */
    @Retryable(value = RuntimeException.class, maxAttempts = 3, backoff = @Backoff(value = 3000L), recover = "testRecover", listeners = {"myRetryListener"})
    public void test() {
        commonService.test("注解式");
    }

    @Recover
    public void testRecover(RuntimeException runtimeException) {
        commonService.recover("注解式");
    }
}

6 启动打印效果

2022-05-06 11:53:12.044  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : =======================================================================
2022-05-06 11:53:12.044  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程开启了
2022-05-06 11:53:12.048  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 1
2022-05-06 11:53:12.048  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 2
2022-05-06 11:53:12.049 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 注解式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:12.049  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:15.062  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 1
2022-05-06 11:53:15.062  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 2
2022-05-06 11:53:15.062 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 注解式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:15.062  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:18.065  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 1
2022-05-06 11:53:18.065  INFO 21812 --- [           main] c.e.s.service.CommonService              : 注解式:打印次数: 2
2022-05-06 11:53:18.065 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 注解式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:18.065  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:18.066 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 注解式:还是有异常,程序有bug哦
2022-05-06 11:53:18.066  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程关闭了
2022-05-06 11:53:18.066  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : =======================================================================
2022-05-06 11:53:18.067  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : =======================================================================
2022-05-06 11:53:18.067  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程开启了
2022-05-06 11:53:18.067  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 1
2022-05-06 11:53:18.067  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 2
2022-05-06 11:53:18.067 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 命令式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:18.067  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:21.079  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 1
2022-05-06 11:53:21.079  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 2
2022-05-06 11:53:21.079 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 命令式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:21.079  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 1
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.service.CommonService              : 命令式:打印次数: 2
2022-05-06 11:53:24.082 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 命令式:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程错误了
2022-05-06 11:53:24.082 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 命令式:还是有异常,程序有bug哦
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : 监听到重试过程关闭了
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.listener.MyRetryListener           : =======================================================================
2022-05-06 11:53:24.082  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 1
2022-05-06 11:53:24.083  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 2
2022-05-06 11:53:24.083 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:27.084  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 1
2022-05-06 11:53:27.084  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 2
2022-05-06 11:53:27.084 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:30.090  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 1
2022-05-06 11:53:30.090  INFO 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:打印次数: 2
2022-05-06 11:53:30.090 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:有异常哦,我再试多几次看下还有没异常
2022-05-06 11:53:30.090 ERROR 21812 --- [           main] c.e.s.service.CommonService              : 以前的做法:还是有异常,程序有bug哦


三、总结

本文仅仅简单介绍了spring-retry的基本使用,相较于以往的做法,个人认为注解式更为简便,命令式看个人喜好,更多使用方法参照github主页

https://github.com/spring-projects/spring-retry

四、示例源码

https://gitee.com/teajoy/springboot-modules/tree/master/springboot-retry

版权声明:程序员胖胖胖虎阿 发表于 2022年11月2日 上午11:32。
转载请注明:spring-retry使用介绍 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...