本篇文章为你整理了Spring Retry 重试()的详细内容,包含有 Spring Retry 重试,希望能帮助你了解 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 () {
@Override
public String doWithRetry(RetryContext context) throws Throwable {
return helloService.hello(code);
return resp;
}
定义一个RetryTemplate,然后调用execute方法,可配置项比较多,不一一列举
真正使用的时候RetryTemplate可以定义成一个Bean,例如:
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.fixedBackoff(1000)
.withListener(new MyRetryListener())
.retryOn(RemoteAccessException.class)
.build();
return retryTemplate;
}
业务代码:
/**
* 命令式的方式使用Spring Retry
@Override
public 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 {
@Override
public T, E extends Throwable boolean open(RetryContext context, RetryCallback T, E callback) {
System.out.println("open");
return true;
@Override
public T, E extends Throwable void close(RetryContext context, RetryCallback T, E callback, Throwable throwable) {
System.out.println("close");
@Override
public T, E extends Throwable void onError(RetryContext context, RetryCallback T, E callback, Throwable throwable) {
System.out.println("error");
}
声明式(注解方式)
/**
* 注解的方式使用Spring Retry
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(value = 1000, delay = 2000, multiplier = 0.5))
@Override
public String hi(int code) {
System.out.println("方法被调用");
int a = 1/code;
return "ok";
@Recover
public 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
@EnableRetry
public class Application {
@Service
class Service {
@Retryable(RemoteAccessException.class)
public void service() {
// ... do something
@Recover
public 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;
}
基本回调是一个简单的接口,允许插入一些要重试的业务逻辑:
public interface RetryCallback T {
T doWithRetry(RetryContext context) throws Throwable;
}
回调函数被尝试,如果失败(通过抛出异常),它将被重试,直到成功或实现决定中止。
RetryOperations最简单的通用实现是RetryTemplate
RetryTemplate template = new RetryTemplate();
TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);
template.setRetryPolicy(policy);
Foo result = template.execute(new RetryCallback Foo () {
public Foo doWithRetry(RetryContext context) {
// Do stuff that might fail, e.g. webservice operation
return result;
});
从Spring Retry 1.3开始,RetryTemplate支持流式配置:
RetryTemplate.builder()
.maxAttempts(10)
.exponentialBackoff(100, 2, 10000)
.retryOn(IOException.class)
.traversingCauses()
.build();
RetryTemplate.builder()
.fixedBackoff(10)
.withinMillis(3000)
.build();
RetryTemplate.builder()
.infiniteRetry()
.retryOn(IOException.class)
.uniformRandomBackoff(1000, 3000)
.build();
3. RecoveryCallback
当重试耗尽时,RetryOperations可以将控制传递给不同的回调:RecoveryCallback。
Foo foo = template.execute(new RetryCallback Foo () {
public Foo doWithRetry(RetryContext context) {
// business logic here
new RecoveryCallback Foo () {
Foo recover(RetryContext context) throws Exception {
// recover logic here
});
4. Listeners
public interface RetryListener {
void open(RetryContext context, RetryCallback T callback);
void onSuccess(RetryContext context, T result);
void onError(RetryContext context, RetryCallback T callback, Throwable e);
void close(RetryContext context, RetryCallback T callback, Throwable e);
}
在最简单的情况下,open和close回调在整个重试之前和之后,onSuccess和onError应用于个别的RetryCallback调用,onSuccess方法在成功调用回调之后被调用。
5. 声明式重试
有时,你希望在每次业务处理发生时都重试一些业务处理。这方面的典型例子是远程服务调用。Spring Retry提供了一个AOP拦截器,它将方法调用封装在RetryOperations实例中。RetryOperationsInterceptor执行被拦截的方法,并根据提供的RepeatTemplate中的RetryPolicy在失败时重试。
你可以在 @Configuration 类上添加一个 @EnableRetry 注解,并且在你想要进行重试的方法(或者类)上添加 @Retryable 注解,还可以指定任意数量的重试监听器。
@Configuration
@EnableRetry
public class Application {
@Bean
public Service service() {
return new Service();
@Bean public RetryListener retryListener1() {
return new RetryListener() {...}
@Bean public RetryListener retryListener2() {
return new RetryListener() {...}
@Service
class Service {
@Retryable(RemoteAccessException.class)
public service() {
// ... do something
}
可以使用 @Retryable 的属性类控制 RetryPolicy 和 BackoffPolicy
@Service
class Service {
@Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))
public service() {
// ... do something
}
如果希望在重试用尽时采用替代代码返回,则可以提供恢复方法。方法应该声明在与@Retryable实例相同的类中,并标记为@Recover。返回类型必须匹配@Retryable方法。恢复方法的参数可以包括抛出的异常和(可选地)传递给原始可重试方法的参数(或者它们的部分列表,只要在需要的最后一个之前不省略任何参数)。
@Service
class Service {
@Retryable(RemoteAccessException.class)
public void service(String str1, String str2) {
// ... do something
@Recover
public void recover(RemoteAccessException e, String str1, String str2) {
// ... error handling making use of original args if required
}
若要解决可选择用于恢复的多个方法之间的冲突,可以显式指定恢复方法名称。
@Service
class Service {
@Retryable(recover = "service1Recover", value = RemoteAccessException.class)
public void service1(String str1, String str2) {
// ... do something
@Retryable(recover = "service2Recover", value = RemoteAccessException.class)
public void service2(String str1, String str2) {
// ... do something
@Recover
public void service1Recover(RemoteAccessException e, String str1, String str2) {
// ... error handling making use of original args if required
@Recover
public void service2Recover(RemoteAccessException e, String str1, String str2) {
// ... error handling making use of original args if required
}
https://github.com/spring-projects/spring-retry
以上就是Spring Retry 重试()的详细内容,想要了解更多 Spring Retry 重试的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。