背景
日常的开发工作中,不免有调用方法失败而发起重试的功能。比如:远程调用失败需要重试、消息发送失败的重发、抢锁失败后的重试等等,都会使用到重试功能点。
是什么
Spring系列的spring-retry是另一个实用程序模块,可以帮助我们以标准方式处理任何特定操作的重试。在spring-retry中,所有配置都是基于简单注释的。
使用步骤
引入依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
启用重试
@EnableRetry
@EnableEncryptableProperties
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
}
方法上加@Retryable
@Override
@Retryable(value = Exception.class,maxAttempts = 4,backoff = @Backoff(delay = 2000L,multiplier = 1.5))
public int retry(String name) throws Exception {
System.out.println("name = " + name + " " + LocalDateTime.now());
if (Objects.equals(name,"test")){
throw new Exception("异常");
}
System.out.println("name = " + name + "success");
return 0;
}
@Retryable 参数含义:
● value:抛出指定异常才会重试
● include:和value一样,默认为空,当exclude也为空时,默认所有异常
● exclude:指定不处理的异常
● maxAttempts:最大重试次数,默认3次
● backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
@Recover注解使用
当重试次数完了还是失败该怎么办?
当重试次数完了,依然还是失败,默认是抛出异常,终止线程。spring-retry也是有一个补偿机制的,@Recover,一个用于重试完后的异常处理的注解,可以直接加在方法上。
@Recover
public int recover(Exception e,String name){
System.out.println(e.getMessage());
System.out.println("name = " + name);
return 1;
}
可以看到传参里面写的是 Exception e,这个是作为回调的对应(重试次数用完了,还是失败,我们抛出这个Exception e通知触发这个回调方法)。
对于@Recover注解的方法,需要特别注意的是:
● 方法的返回值必须与@Retryable方法一致
● 方法的第一个参数,必须是Throwable类型的,建议是与@Retryable配置的异常一致,其他的参数,需要哪个参数,写进去就可以了(@Recover方法中有的)
● 该回调方法与重试方法写在同一个实现类里面
注意
● 由于是基于AOP实现,所以不支持类里自调用方法
● 如果重试失败需要给@Recover注解的方法做后续处理,那这个重试的方法不能有返回值,只能是void
● 方法内不能使用try catch,只能往外抛异常
● @Recover注解来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中),此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。