在日常的一些场景中, 很多需要进行重试的操作.而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/


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


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


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


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

#comment_body_3242240 { display: none }

SpringBoot进阶教程(八十四)spring-retry的更多相关文章

  1. SpringBoot进阶教程(六十四)注解大全

    在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...

  2. SpringBoot进阶教程(七十四)整合ELK

    在上一篇文章<SpringBoot进阶教程(七十三)整合elasticsearch >,已经详细介绍了关于elasticsearch的安装与使用,现在主要来看看关于ELK的定义.安装及使用 ...

  3. SpringBoot进阶教程(二十四)整合Redis

    缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力.Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非 ...

  4. SpringBoot进阶教程(六十五)自定义注解

    在上一篇文章<SpringBoot进阶教程(六十四)注解大全>中介绍了springboot的常用注解,springboot提供的注解非常的多,这些注解简化了我们的很多操作.今天主要介绍介绍 ...

  5. SpringBoot进阶教程(二十九)整合Redis 发布订阅

    SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不用编程就可以向特定的接受者发送消息 (subscribers). Ra ...

  6. SpringBoot进阶教程(五十九)整合Codis

    上一篇博文<详解Codis安装与部署>中,详细介绍了codis的安装与部署,这篇文章主要介绍介绍springboot整合codis.如果之前看过<SpringBoot进阶教程(五十二 ...

  7. SpringBoot进阶教程(六十八)Sentinel实现限流降级

    前面两篇文章nginx限流配置和SpringBoot进阶教程(六十七)RateLimiter限流,我们介绍了如何使用nginx和RateLimiter限流,这篇文章介绍另外一种限流方式---Senti ...

  8. SpringBoot进阶教程(二十八)整合Redis事物

    Redis默认情况下,事务支持被禁用,必须通过设置setEnableTransactionSupport(true)为使用中的每个redistplate显式启用.这样做会强制将当前重新连接绑定到触发m ...

  9. SpringBoot进阶教程(二十六)整合Redis之共享Session

    集群现在越来越常见,当我们项目搭建了集群,就会产生session共享问题.因为session是保存在服务器上面的.那么解决这一问题,大致有三个方案,1.通过nginx的负载均衡其中一种ip绑定来实现( ...

  10. SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

    在上一篇文章(<SpringBoot(二十四)整合Redis>)中,已经实现了Spring Boot对Redis的整合,既然已经讲到Cache了,今天就介绍介绍缓存注解.各家互联网产品现在 ...

随机推荐

  1. Java消息队列入门详解

    什么是消息队列? 消息队列的产生主要是为了解决系统间的异步解耦与确保最终一致性.在实际应用场景中,往往存在一些主流程操作和辅助流程操作,其中主流程需要快速响应用户请求,而辅助流程可能涉及复杂的处理逻辑 ...

  2. myBatis插入操作获取不到返回的自增id问题

    myBatis插入操作后想返回自增 id 有多种方式 其中一种使用率较高的就是: 在<insert></insert> 标签中添加 useGeneratedKeys 和 key ...

  3. CSS:Transform属性

    本文将深入探讨css动画中transform属性,这是一种强大的工具,可以实现元素的旋转.缩放.移动和倾斜等效果.本文将通过详细的解释和实际案例,帮助你掌握transform属性的使用方法来增强你的网 ...

  4. 使用MySQL Workbench进行数据库备份

    1.打开MySQL Workbench 2.进行数据库连接配置 如果之前连过,会有历史记录,直接点击需要备份的连接即可 3.进入主界面后,选择左侧的Administration选项卡,然后点击Data ...

  5. 4.7 Linux压缩文件或目录中文件为.bz2格式(bzip2命令)

    bzip2 命令同 gzip 命令类似,只能对文件进行压缩(或解压缩),对于目录只能压缩(或解压缩)该目录及子目录下的所有文件.当执行压缩任务完成后,会生成一个以".bz2"为后缀 ...

  6. 3.15 Linux复制文件和目录(cp命令)

    cp 命令,主要用来复制文件和目录,同时借助某些选项,还可以实现复制整个目录,以及比对两文件的新旧而予以升级等功能. cp 命令的基本格式如下: [root@localhost ~]# cp [选项] ...

  7. 自动化构建镜像:Packer

    在介绍Packer之前,先来回顾一下未使用Packer时自定义虚拟机镜像的步骤.先在本地启动一个虚拟机,从安装系统开始,再进行自定义配置或应用安装,最后封装压缩成镜像,详细操作步骤可以参考我之前写的文 ...

  8. laravel框架之ORM操作

    Laravel 支持原生的 SQL 查询.流畅的查询构造器 和 Eloquent ORM 三种查询方式: 流畅的查询构造器(简称DB),它是为创建和运行数据库查询提供的一个接口,支持大部分数据库操作, ...

  9. MySQL底层概述—9.ACID与事务

    大纲 1.ACID之原子性 2.ACID之持久性 3.ACID之隔离性 4.ACID之一致性 5.ACID的关系 6.事务控制演进之排队 7.事务控制演进之排它锁 8.事务控制演进之读写锁 9.事务控 ...

  10. 用谷歌经典ML方法方法来设计生成式人工智能语言模型

    上一篇:<人工智能模型学习到的知识是怎样的一种存在?> 序言:在接下来的几篇中,我们将学习如何利用 TensorFlow 来生成文本.需要注意的是,我们这里并不使用当前最热门的 Trans ...