重试的使用场景比较多,比如调用远程服务时 , 由于网络或者服务端响应慢导致调用超时,此时可以多重试几次 。用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有 。话不多说,先看演示 。
首先引入依赖
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.4</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.9.1</version></dependency>
使用方式有两种:命令式和声明式
命令式/** * 命令式的方式使用Spring Retry */@GetMapping("/hello")public String hello(@RequestParam("code") Integer code) throws Throwable {RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(3).fixedBackoff(1000).retryOn(RemoteAccessException.class).build();retryTemplate.registerListener(new MyRetryListener());String resp = retryTemplate.execute(new RetryCallback<String, Throwable>() {@Overridepublic String doWithRetry(RetryContext context) throws Throwable {return helloService.hello(code);}});return resp;}
定义一个RetryTemplate,然后调用execute方法,可配置项比较多 , 不一一列举
真正使用的时候RetryTemplate可以定义成一个Bean,例如:
@Configurationpublic class RetryConfig {@Beanpublic RetryTemplate retryTemplate() {RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(3).fixedBackoff(1000).withListener(new MyRetryListener()).retryOn(RemoteAccessException.class).build();return retryTemplate;}}
业务代码:
/** * 命令式的方式使用Spring Retry */@Overridepublic String hello(int code) {if (0 == code) {System.out.println("出错了");throw new RemoteAccessException("出错了");}System.out.println("处理完成");return "ok";}
文章插图
文章插图
文章插图
监听器实现:
package com.example.retry.listener;import org.springframework.retry.RetryCallback;import org.springframework.retry.RetryContext;import org.springframework.retry.RetryListener;public class MyRetryListener implements RetryListener {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("open");return true;}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("close");}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("error");}}
声明式(注解方式)/** * 注解的方式使用Spring Retry */@Retryable(value = https://www.huyubaike.com/biancheng/Exception.class, maxAttempts = 2, backoff = @Backoff(value = 1000, delay = 2000, multiplier = 0.5))@Overridepublic String hi(int code) {System.out.println("方法被调用");int a = 1/code;return "ok";}@Recoverpublic String hiRecover(Exception ex, int code) {System.out.println("重试结束");return "asdf";}
这里需要主要的几点- @EnableRetry(proxyTargetClass = true/false)
- @Retryable 修饰的方法必须是public的,而且不能是同一个类中调用
- @Recover 修饰的方法签名必须与@Retryable修饰的方法一样,除了第一个参数外
/** * 注解的方式使用Spring Retry */@GetMapping("/hi")public String hi(@RequestParam("code") Integer code) {return helloService.hi(code);}
文章插图
文章插图
文章插图
文章插图
1. 用法
声明式
@Configuration@EnableRetrypublic class Application {}@Serviceclass Service {@Retryable(RemoteAccessException.class)public void service() {// ... do something}@Recoverpublic void recover(RemoteAccessException e) {// ... panic}}
命令式RetryTemplate template = RetryTemplate.builder().maxAttempts(3).fixedBackoff(1000).retryOn(RemoteAccessException.class).build();template.execute(ctx -> {// ... do something});
2. RetryTemplate为了自动重试,Spring Retry 提供了 RetryOperations 重试操作策略
public interface RetryOperations {<T> T execute(RetryCallback<T> retryCallback) throws Exception;<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)throws Exception;<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)throws Exception, ExhaustedRetryException;<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,RetryState retryState) throws Exception;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 四十八 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存
- 装配 SpringBoot自动配置流程
- 四十七 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
- SpringCloud怎么迈向云原生?
- Filter Spring中过滤器和拦截器(Interceptor)的区别和联系
- 二 SpringCloud - Eureka注册中心,feign远程调用,hystrix降级和熔断
- 二 【SSM】学习笔记——SpringMVC入门
- 四十六 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
- Springboot 一行代码实现文件上传 20个平台!少写代码到极致