• Spring Retry方法重试



    介绍

    Spring Retry是Spring框架提供的用于处理重试操作的模块。它旨在简化在应用程序中处理失败和异常情况的重试逻辑。

    使用

    1. 引入依赖

      <dependency>
          <groupId>org.springframework.retrygroupId>
          <artifactId>spring-retryartifactId>
          <version>1.3.1version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 启用重试

      Spring配置类上添加@EnableRetry注解,启用重试功能。

    3. 使用重试

      • @Retryable注解方式
      • RetryTemplate模板方式

    注解方式:@Retryable

    当使用@Retryable注解的方法在执行时发生异常时,Spring将自动重试该方法,直到方法成功执行或达到最大重试次数。

    Retryable注解的属性

    • interceptor

      说明:该属性用于指定一个重试拦截器。重试拦截器可以在每次重试之前或之后执行特定操作,例如记录日志、执行某些额外的逻辑等。通过指定拦截器,可以对重试过程进行更精细的控制和扩展。

      注意:interceptor属性与其它属性是互斥的。

      用途:通常用于实现自定义的重试逻辑、日志记录、性能统计等。

    • value

      说明:该属性用于指定触发重试的异常类型。它是一个Class类型的数组,可以指定一个或多个异常类。只有当方法抛出指定类型的异常时,才会触发重试机制。

      注意:value与include类型类似,优先级高于include。默认为空(如果exclude排除也为空,则重试所有异常)

      用途:用于定义哪些异常应该触发重试策略,可以根据具体业务需求和异常类型进行设置。

    • include

      说明:该属性用于指定必须包含在内的异常类型,只有这些异常会触发重试。与value属性相似,但优先级低于value。如果同时指定了include和value,则以value为准。

      注意:include与value类型类似,优先级低于include。默认为空(如果exclude排除也为空,则重试所有异常)

      用途:在某些情况下,你可能只想对特定的异常进行重试,而不是对所有异常都进行重试。

    • exceptionExpression

      说明:该属性是一个SpEL(Spring Expression Language)表达式,用于进一步定义哪些异常应该触发重试。它允许根据异常的详细信息进行更灵活的控制。

      用途:用于根据自定义表达式来决定是否进行重试,例如根据异常的特定属性、消息内容等。

    • exclude

      说明:该属性用于指定需要排除的异常类型,即使它们匹配了value、include或exceptionExpression指定的条件,也不会触发重试。

      注意:如果include为空但exclude不为空,则重试所有未排除的异常。

      用途:用于明确排除某些异常,确保它们不会触发重试机制。

    • label

      说明:为重试策略提供一个标签。这个标签可以用于日志、监控或其他目的,以区分不同的重试策略。

      用途:帮助在多个重试策略中进行标识和区分。

    • stateful

      说明:表示该重试是有状态的还是无状态的。默认为false(无状态)。在有状态重试中,每次尝试可能会受之前尝试的影响。

      用途:适用于那些前一次尝试的结果会影响下一次尝试的场景。

    • maxAttempts

      说明:该属性用于设置最大重试次数(包括第1次调用)。它表示在方法连续失败的情况下,最多可以尝试多少次重试。当达到最大重试次数后,如果方法仍然失败,将不再继续重试。

      用途:用于控制重试的次数,避免无限循环重试导致的资源浪费和性能问题。

    • maxAttemptsExpression

      说明:与maxAttempts功能类似,但它接受一个SpEL表达式,用于动态地计算最大重试次数。

      用途:为最大重试次数提供动态配置能力,根据实际运行时的参数、环境变量等来决定最大重试次数。

    • backoff

      说明:该属性用于配置退避策略,即两次连续重试之间的延迟策略等。常见的策略包括固定延迟和指数延迟。属性指定一个@Backoff注解

      Backoff注解的属性:

      • value:用于指定重试间隔的起始值(默认为 1000 毫秒)。
      • delay:用于指定固定的重试间隔(默认为 0)。
      • maxDelay:用于指定重试间隔的最大值(默认为 0,表示没有最大间隔限制)。
      • multiplier:用于计算下一个重试间隔的倍数(默认为 0,表示不使用指数级增长)。
      • maxDelayExpression:用于指定重试间隔的最大表达式,允许你使用 SpEL 表达式动态地计算最大的重试间隔。
      • multiplierExpression:用于指定重试间隔的倍数表达式,允许你使用 SpEL 表达式动态地计算重试间隔的倍数。
      • random:用于指定是否使用随机间隔时间(默认为 false)。

      用途:通过设置合适的退避策略,可以避免频繁的重试对系统造成过大压力,同时合理分散请求,提高系统的可用性和稳定性。

    • listeners

      说明:定义重试事件的监听器。这些监听器可以捕获到重试的开始、结束、失败等事件,并据此执行相应的操作。

      用途:用于实现自定义的重试事件处理逻辑,如发送通知、记录详细日志等。

    Retryable注解的使用

    1. 定义重试方法:在您希望进行重试的方法上添加@Retryable注解。

      @Retryable注解的属性:

      • value:指定需要重试的异常类型。可以是单个异常类型或异常类型数组。
      • maxAttempts:指定最大重试次数。
      • backoff:指定重试间隔和退避策略。
    2. 定义重试失败处理方法:如果达到最大重试次数但仍然失败,可以使用@Recover注解在另一个方法中定义重试失败的处理逻辑。

    @RestController
    @RequestMapping(value = "/retry")
    public class RetryController {
    
        @Autowired
        private RetryTest retryTest;
    
        @GetMapping(value = "testAnnotation")
        public ApiResult test() {
            retryTest.test();
            return ApiUtil.success();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    @EnableRetry
    @Component
    public class RetryTest {
    
        @Retryable(
                value = {Exception.class},                          // 指定需要重试的异常类型
                maxAttempts = 3,                                    // 最大重试次数
                backoff = @Backoff(delay = 1000, multiplier = 2)    // 重试间隔和退避策略
        )
        public void test() {
            System.out.println("RetryTest.test() 调用"+ DateUtil.formatDateTime(new Date()));
            int i = 1 / 0;
        }
    
        @Recover
        public void recover(Exception e) {
            System.out.println("RetryTest.test() 重试仍然失败了");
            System.out.println(e);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    日志

    RetryTest.test() 调用2023-11-13 22:17:03
    RetryTest.test() 调用2023-11-13 22:17:04
    RetryTest.test() 调用2023-11-13 22:17:06
    RetryTest.test() 重试仍然失败了
    java.lang.ArithmeticException: / by zero
    
    • 1
    • 2
    • 3
    • 4
    • 5

    模板方式:RetryTemplate

    使用RetryTemplate模板实现重试。

    @Configuration
    public class RetryTemplateConfig {
    
        @Bean
        public RetryTemplate retryTemplate() {
            RetryTemplate retryTemplate = new RetryTemplate();
    
            // 定义重试策略
            SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
            retryPolicy.setMaxAttempts(3); // 最大重试次数
            retryTemplate.setRetryPolicy(retryPolicy);
    
            // 定义重试间隔
            ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
            backOffPolicy.setInitialInterval(1000);
            backOffPolicy.setMultiplier(2);
            retryTemplate.setBackOffPolicy(backOffPolicy);
    
            return retryTemplate;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    @RestController
    @RequestMapping(value = "/retry")
    public class RetryController {
    
        @Autowired
        private RetryTest retryTest;
        @Autowired
        private RetryTemplate retryTemplate;
    
        @GetMapping(value = "testAnnotation")
        public ApiResult test() {
            retryTest.test();
            return ApiUtil.success();
        }
    
        @GetMapping(value = "testTemplate")
        public ApiResult test1() {
            retryTemplate.execute(
                    retryContext -> {
                        // 业务逻辑
                        System.out.println("RetryTest.test() 调用"+ DateUtil.formatDateTime(new Date()));
                        int i = 1 / 0;
                        return null;
                        },
                    retryContext -> {
                        System.out.println("RetryTest.test() 重试仍然失败了");
                        System.out.println(retryContext.getLastThrowable());
                        return null;
                    });
            return ApiUtil.success();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    日志

    RetryTest.test() 调用2023-11-13 22:24:05
    RetryTest.test() 调用2023-11-13 22:24:06
    RetryTest.test() 调用2023-11-13 22:24:08
    RetryTest.test() 重试仍然失败了
    java.lang.ArithmeticException: / by zero
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    一文看懂Transformer(详解)
    【Java】String、StringBuilder、StringBuffer的介绍和区分
    机器学习(22)---信息熵、纯度、条件熵、信息增益
    JAVA毕业设计Web企业客户管理系统计算机源码+lw文档+系统+调试部署+数据库
    BATJ高频面试249道题:微服务+多线程+分布式+MyBatis +Spring
    React Hook之useContext
    java基础-第4章-面向对象(二)
    ESP32外部中断原理详解及代码示例
    1_SpringMVC_概述,2_SpringMVC_项目搭建
    Java23种设计模式-行为型模式之策略模式
  • 原文地址:https://blog.csdn.net/JokerLJG/article/details/132189011