Spring Retry 重试

重试的使用场景比较多,比如调用远程服务时 , 由于网络或者服务端响应慢导致调用超时,此时可以多重试几次 。用定时任务也可以实现重试的效果,但比较麻烦,用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";}

Spring Retry 重试

文章插图

Spring Retry 重试

文章插图

Spring Retry 重试

文章插图
监听器实现:
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";}这里需要主要的几点
  1. @EnableRetry(proxyTargetClass = true/false)
  2. @Retryable 修饰的方法必须是public的,而且不能是同一个类中调用
  3. @Recover 修饰的方法签名必须与@Retryable修饰的方法一样,除了第一个参数外
/** * 注解的方式使用Spring Retry */@GetMapping("/hi")public String hi(@RequestParam("code") Integer code) {return helloService.hi(code);}
Spring Retry 重试

文章插图

Spring Retry 重试

文章插图

Spring Retry 重试

文章插图

Spring Retry 重试

文章插图
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;}

推荐阅读