英文:
Spring Boot @Retryable maxAttempts according to exception
问题
关于Spring Boot的@Retryable
注解,我有一个疑问。
我想根据异常类型来实现@Retryable
的最大尝试次数,就像这样:
如果异常类型是ExceptionA:
@Retryable(value = ExceptionA.class, maxAttempts = 2)
如果异常类型是ExceptionB:
@Retryable(value = ExceptionB.class, maxAttempts = 5)
是否可以使用@Retryable
注解来实现这个功能,或者是否有什么建议?
英文:
I wonder something about Spring Boot @Retryable
annotation.
I want to implement @Retryable
maxAttemps count according to Exception type, like:
if Exception type is ExceptionA:
@Retryable(value = ExceptionA.class, maxAttempts = 2)
if Exception type is ExceptionB:
@Retryable(value = ExceptionB.class, maxAttempts = 5)
Is it possible to do it with @Retryable
annotation, or is there any suggestion?
答案1
得分: 1
不直接进行; 您需要构建一个自定义的拦截器 (RetryInterceptorBuilder
) bean,并在 @Retryable.interceptor
中提供其 bean 名称。
使用 ExceptionClassifierRetryPolicy
为每个异常使用不同的策略。
编辑
这里是一个示例:
@SpringBootApplication
@EnableRetry
public class So64029544Application {
public static void main(String[] args) {
SpringApplication.run(So64029544Application.class, args);
}
@Bean
public ApplicationRunner runner(Retryer retryer) {
return args -> {
retryer.toRetry("state");
retryer.toRetry("arg");
};
}
@Bean
public Object retryInterceptor(Retryer retryer) throws Exception {
ExceptionClassifierRetryPolicy policy = new ExceptionClassifierRetryPolicy();
policy.setPolicyMap(Map.of(
IllegalStateException.class, new SimpleRetryPolicy(2),
IllegalArgumentException.class, new SimpleRetryPolicy(3)));
Method recover = retryer.getClass().getDeclaredMethod("recover", Exception.class);
return RetryInterceptorBuilder.stateless()
.retryPolicy(policy)
.backOffOptions(1_000, 1.5, 10_000)
.recoverer(new RecoverAnnotationRecoveryHandler<>(retryer, recover))
.build();
}
}
@Component
class Retryer {
@Retryable(interceptor = "retryInterceptor")
public void toRetry(String in) {
System.out.println(in);
if ("state".equals(in)) {
throw new IllegalStateException();
}
else {
throw new IllegalArgumentException();
}
}
@Recover
public void recover(Exception ex) {
System.out.println("Recovered from " + ex
+ ", retry count:" + RetrySynchronizationManager.getContext().getRetryCount());
}
}
state
state
Recovered from java.lang.IllegalStateException, retry count:2
arg
arg
arg
Recovered from java.lang.IllegalArgumentException, retry count:3
英文:
Not directly; you would have to construct a custom interceptor (RetryInterceptorBuilder
) bean and provide its bean name in @Retryable.interceptor
.
Use an ExceptionClassifierRetryPolicy
to use a different policy for each exception.
EDIT
Here's an example:
@SpringBootApplication
@EnableRetry
public class So64029544Application {
public static void main(String[] args) {
SpringApplication.run(So64029544Application.class, args);
}
@Bean
public ApplicationRunner runner(Retryer retryer) {
return args -> {
retryer.toRetry("state");
retryer.toRetry("arg");
};
}
@Bean
public Object retryInterceptor(Retryer retryer) throws Exception {
ExceptionClassifierRetryPolicy policy = new ExceptionClassifierRetryPolicy();
policy.setPolicyMap(Map.of(
IllegalStateException.class, new SimpleRetryPolicy(2),
IllegalArgumentException.class, new SimpleRetryPolicy(3)));
Method recover = retryer.getClass().getDeclaredMethod("recover", Exception.class);
return RetryInterceptorBuilder.stateless()
.retryPolicy(policy)
.backOffOptions(1_000, 1.5, 10_000)
.recoverer(new RecoverAnnotationRecoveryHandler<>(retryer, recover))
.build();
}
}
@Component
class Retryer {
@Retryable(interceptor = "retryInterceptor")
public void toRetry(String in) {
System.out.println(in);
if ("state".equals(in)) {
throw new IllegalStateException();
}
else {
throw new IllegalArgumentException();
}
}
@Recover
public void recover(Exception ex) {
System.out.println("Recovered from " + ex
+ ", retry count:" + RetrySynchronizationManager.getContext().getRetryCount());
}
}
state
state
Recovered from java.lang.IllegalStateException, retry count:2
arg
arg
arg
Recovered from java.lang.IllegalArgumentException, retry count:3
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论