-
项目中很多时候会用到重试,比如在网络出现异常的时候调用第三方接口就会出现异常,在这个时候有个可以自动重试的方法就非常方便了。而springboot的Retryable就跟好的解决了这个问题。
-
老规矩先上需要导入的包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
-
在项目的启动类上加上一个开始重试的注解@EnableRetry
@EnableRetry @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class,args); } }
-
创建一个测试的controller和service以及service的实现类
@Api(tags = "测试") @RestController @RequestMapping("/test") public class TestController { @Autowired private TestServices testServices; @ApiOperation(value = "自动重试") @GetMapping("/runRetry") public Result<String> runRetry(){ testServices.saveVideo(new Test()); return Result.success(); } } public interface TestServices { void saveVideo(Test test); } @Slf4j @Service public class TestServicesImpl implements TestServices { //指定使用自定义名为taskExecutor的线程池来执行该任务,如果没有就不填使用springboot自带的 @Async("taskExecutor") @Retryable(value = Exception.class,maxAttempts = 4,backoff = @Backoff(delay = 4000L,multiplier = 2)) @Override public void saveVideo(Test test) { String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())); log.info("任务开始:{}",startTime); test.getStatus(); String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())); log.info("任务结束:{}",endTime); } @Recover public void recover() { log.error("任务结束出现异常:连接超时"); } } public class Test { public boolean getStatus(){ RestTemplate restTemplate=new RestTemplate(); restTemplate.getForObject("192.168.6.100",String.class); return false; } }
-
重点解释一下@Retryable的参数
value:代发触发的条件,值得是拦截捕获的异常。
maxAttempts:重试的最大次数。
delay:每次重试的时间间隔,单位是毫秒。
multiplier:是重试间隔的增长系数,比如时间间隔为4秒 系数为2,那么第二次的重试的间隔就是4秒,第三次就是8秒,第四次就是16秒.
@Recover 注解注释的方法 就是当重试次数全部完成依然还为解决,就会执行@Recover修饰的方法 -
看一下控制台的打印
-
可以看到控制台打印的时间间隔,刚好就是相隔4.8.16秒。最后也走了recover方法。
-
最后说几个重点也是我自己给自己挖的坑
1.逻辑代码最好不要用try catch捕获异常,即使捕获了记得要再次抛出。try { String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())); log.info("任务开始:{}",startTime); test.getStatus(); String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())); log.info("任务结束:{}",endTime); } catch (IllegalArgumentException Ie){ log.info("restTemplate出现异常 任务结束出现异常:{}",Ie.getMessage()); Ie.printStackTrace(); } catch (IORuntimeException Io){ log.info("IORuntimeException出现异常 任务结束出现异常:{}",Io.getMessage()); Io.printStackTrace(); } catch (Exception e) { log.info("任务结束出现异常:{}",e.getMessage()); e.printStackTrace(); }
2.这是我最之前写的,因为把异常捕获了,所以就一直触发不了@Retryable。找了很久的原因才找到。真的是自己坑自己。
3.使用@Retryable修饰方法的类,一定要通过@Autowired注入进去,不能手动的new,目的就是为了加入spring boot的管理中,否则就是无效。 -
本次分享就到这里。如有理解错误的地方欢迎指出讨论。
相关文章
- 11-08记录:使用springboot的cors和vue的axios进行跨域
- 11-08SpringBoot中在除Controller层 使用Validation的方式
- 11-08Zipkin初探 + 与SpringBoot的集成+ 使用HTTP方式传送数据给zipkin server
- 11-08Cypress系列(6)- Cypress 的重试机制
- 11-08springboot2.x分别使用freemarker,thymeleaf,velocity发送邮件(包括带附件的)到qq邮箱
- 11-08springboot使用freemarker模块的常用使用
- 11-08SpringBoot学习笔记(4)----SpringBoot中freemarker、thymeleaf的使用
- 11-08SpringBoot2.x基础篇:灵活的使用外部化配置信息
- 11-08SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解
- 11-08日志系列---【springboot中使用日志的正确打开方式】