SpringBoot进阶教程(八十四)spring-retry

在日常的一些场景中, 很多需要进行重试的操作.而spring-retry是spring提供的一个基于spring的重试框架,某些场景需要对一些异常情况下的方法进行重试就会用到spring-retry。spring-retry可以帮助我们以标准方式处理任何特定操作的重试。在spring-retry中,所有配置都是基于简单注释的。

v添加引用

复制代码
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

v启用@Retryable

复制代码
@SpringBootApplication
@EnableRetry
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

}

要使用@EnabelRetry开启重试才行,声明在配置类或者启动类上都可以激活。

v在方法上添加@Retryable

创建service接口

复制代码
public interface HomeService {
    int convertStatus(int status) throws Exception;
}

在service实现类并添加@Retryable

复制代码
@Slf4j
@Service
public class HomeServiceImpl implements HomeService {
    /**
     * value:抛出指定异常才会重试
     * include:和value一样,默认为空,当exclude也为空时,默认所有异常
     * exclude:指定不处理的异常
     * maxAttempts:最大重试次数,默认3次(包括第一次调用)
     * backoff:重试等待策略,
     * 默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000; 以毫秒为单位的延迟(默认 1000);delay:重试的间隔时间,就是value
     * multiplier delay时间的间隔倍数,默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
     * @param status
     * @return
     * @throws Exception
     */
    @Override
    @Retryable(retryFor = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public int convertStatus(int status) throws Exception{
        System.out.println("进入convertStatus时间:"+ LocalTime.now());
        if (status < 0){
            throw new Exception("状态小于0是非法的");
        }

        System.out.println("convertStatus: status++");

        return status++;
    }

    /**
     * Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法。
     * 如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。
     * @Recover标记方法必须要与@Retryable注解的方法"形参"保持一致,第一入参为要重试的异常(一定要是@Retryable方法里抛出的异常或者异常父类),其他参数与@Retryable保持一致,返回值也要一样,否则无法执行!
     *
     * @param e
     * @param status @Retryable注解的原方法参数,可以保留,也可以不要。
     * @return
     */
    @Recover
    public int recover(Exception e, int status) {
        //记日志到数据库 或者调用其余的方法
        System.out.println(String.format("兜底方法执行,异常信息:%s,status:%d", e.toString(), status));
        return -1;
    }
}

@Retryable修饰的convertStatus()方法,如果调用期间报了异常,那么它将进行重试3次(默认三次),如果超过最大重试次数,则执行@Retryable修饰的recover()方法,
创建controller

复制代码
@Slf4j
@RestController
public class HomeController {
    @Autowired
    HomeService homeService;

    @GetMapping("convertStatus")
    public ReturnValue<?> convertStatus(@RequestParam("token") String token,
                                        @RequestParam("status") int status) throws Exception {
        int result = homeService.convertStatus(status);
        return ReturnValue.buildSuccessResult(result);
    }
}

验证效果

v常用注解介绍

@EnableRetry

启用重试,开启aop的功能,默认使用jdk的动态代理。proxyTargetClass属性为true时(默认false),使用CGLIB代理
@Retryable

标记当前方法会使用重试机制。

|-------------|-----------|------------|-------------------------------------------------|
| 属性 | 类型 | 默认值 | 说明 |
| interceptor | String | "" | 将interceptor的bean名称应用到retryable(),和其他的属性互斥 |
| include | Class[] | {} | 哪些异常可以触发重试 ,默认为空 |
| exclude | Class[] | {} | 哪些异常将不会触发重试,默认为空,如果和include属性同时为空,则所有的异常都将会触发重试 |
| value | Class[] | {} | 可重试的异常类型 |
| label | String | "" | 统计报告的唯---标签。如果没有提供,调用者可以选择忽略它,或者提供默认值 |
| maxAttempts | int | 3 | 尝试的最大次数(包括第一次失败),默认为3次 |
| backoff | @Backoff | @Backoff() | @Backoff @Backoff()指定用于重试此操作的backoff属性。默认为 |

@Backoff

重试回退策略(立即重试还是等待一会再重试)

|------------|---------|---------|---------------------------------|
| 属性 | 类型 | 默认值 | 说明 |
| delay | long | 0 | 如果不设置则默认使用1000 ms等待重试,和value同义词 |
| maxDelay | long | 0 | 最大重试等待时间 |
| multiplier | long | 0 | 用于计算下一个延迟延迟的乘数(大于0生效) |
| random | boolean | FALSE | 随机重试等待时间 |

@Backoff 的参数会影响我们使用哪种退避策略

  • FixedBackOffPolicy
    默认退避策略,每 1 秒重试 1 次
  • ExponentialBackOffPolicy
    指数退避策略,当设置 multiplier 时使用,每次重试时间间隔为 当前延迟时间 * multiplier。
  • ExponentialRandomBackOffPolicy
    指数随机退避策略。在指数退避策略的基础上增加了随机性。具体策略查看 getSleepAndIncrement() 方法
  • UniformRandomBackOffPolicy
    均匀随机策略,设置 maxDely 但没有设置 multiplier 时使用,重试间隔会在 maxDelay 和 delay 间随机

@Recover

作为恢复处理程序的方法调用的注释。重试方法最终会调用标注了@Recover 的方法。

@Recover声明的方法和@Retryable 方法相同类型的返回值,Throwable 第一个参数是可选的(但是,如果没有其他参数匹配,则不带该参数的方法将被调用)。从失败方法的参数列表中依次填充后续参数。

v注意事项

  • 使用了Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable注解的方法直接实例化调用不会触发重试,要先将实现类实例化到Spring容器中,然后通过注入等方式使用
  • Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable标注方法产生的异常不能使用try-catch捕获,要在方法上抛出异常,不然不会触发重试
  • recover方法的返回值必须与Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable方法一致
  • 查询可以进行重试,写操作要慎重,除非业务方支持重入

v源码地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn

作  者:请叫我头头哥

出  处:http://www.cnblogs.com/toutou/

关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信

声援博主:如果您觉得文章对您有帮助,可以点击文章右下角**【推荐】** 一下。您的鼓励是作者坚持原创和持续写作的最大动力!

相关推荐
华年源码3 小时前
基于springboot的房屋租赁系统(源码+数据库+文档)
java·数据库·spring boot·后端·毕业设计·源码·springboot
灰色孤星A1 天前
瑞吉外卖项目学习笔记(十)修改套餐、删除套餐、起售和停售套餐
java·学习笔记·springboot·瑞吉外卖·黑马程序员
Hello Dam1 天前
场馆预定平台高并发时间段预定实现V1
java·springboot·位图·秒杀·场馆预定
一个欧维2 天前
党员学习交流平台
学习·java-ee·毕业设计·springboot·课程设计
Code blocks2 天前
小试牛刀-SpringBoot集成SOL链
java·区块链·springboot
小金的学习笔记3 天前
SpringBootWeb案例-2
java·服务器·springboot·web
华年源码3 天前
基于springboot的课程作业管理系统(源码+数据库+文档)
java·数据库·毕业设计·源码·springboot
Tulipes4 天前
Excel导出功能:vue2+SpringBoot
java·vue·excel·springboot·easyexcel
V+zmm101346 天前
运动健康小程序SpringBoot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·springboot