当有些方法调用因为网络原因调用失败时往往需要重试机制。
1.通过while循环或者捕获异常后做处理。
2.使用spring提供的重试机制,这种方式的好处是基于AOP实现,没有代码入侵。
基于springBoot项目使用@Retryable注解实现重试
1.添加依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
2.在启动类或者配置类上加@EnableRetry注解,启用这个功能
@EnableRetry
public class TestApplication {
public static void main(String[] args) {
try {
SpringApplication.run(TestApplication.class, args);
log.info("[启动成功]");
}catch (Exception e){
log.info("[启动失败]:{}",e);
}
}
}
3.创建一个类,在需要重试的方法上添加注解@Retryable
maxAttempts:尝试次数 默认是3次(3指的是共执行三次)
backoff:可以指定暂停时间(multiplier是递增指数,maxAttempts大于2时起作用)
value:当出现这种异常时,进行重试
@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
public void cacheProduct(String productCode) throws Exception {
}
//尝试了指定次数仍失败后 统一由同一个类中的@Recover注解的方法做处理(类似于全局异常处理的方式)
//注意这个方法也不能有返回值
@Recover
public void recover(Exception e) {
logger.warn("减库存失败!!!" + LocalTime.now());
//记日志到数据库
}
@Retryable注解使用需要注意的地方:
1.由于是基于AOP实现,所以不支持类里自调用方法
3.如果重试失败需要给@Recover注解的方法做后续处理,那这个需要多次重试的方法不能有返回值,只能是void。否则重试结束后如果仍然失败也不会被指定方法处理
4.方法内不能使用try catch处理异常,即使使用了catch也要往外抛出异常
------------------------------------------------------------------------------------------
留言评论说文章写得有问题,贴一下测试代码
“方法所在的类不能是接口的实现类" 似乎是不成立,之前测试可能是因为@Recover注解的方法与重试方法不在同一类中导致重试完后没有被处理而是直接抛出了异常。
3.如果重试的方法有返回值,那么在重试次数用完后如果仍然失败也不会被@Recover注解的方法做处理。
4.如果重试方法中使用了try catch处理了异常而没有抛出去,那么重试不会起作用,第一次异常被处理后就不会再进行重试了