Spring Boot @Retryable 根据异常的 maxAttempts 配置

huangapple go评论154阅读模式
英文:

Spring Boot @Retryable maxAttempts according to exception

问题

关于Spring Boot的@Retryable注解,我有一个疑问。

我想根据异常类型来实现@Retryable的最大尝试次数,就像这样:

如果异常类型是ExceptionA:

  1. @Retryable(value = ExceptionA.class, maxAttempts = 2)

如果异常类型是ExceptionB:

  1. @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:

  1. if Exception type is ExceptionA:
  2. @Retryable(value = ExceptionA.class, maxAttempts = 2)
  3. if Exception type is ExceptionB:
  4. @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 为每个异常使用不同的策略。

编辑

这里是一个示例:

  1. @SpringBootApplication
  2. @EnableRetry
  3. public class So64029544Application {
  4. public static void main(String[] args) {
  5. SpringApplication.run(So64029544Application.class, args);
  6. }
  7. @Bean
  8. public ApplicationRunner runner(Retryer retryer) {
  9. return args -> {
  10. retryer.toRetry("state");
  11. retryer.toRetry("arg");
  12. };
  13. }
  14. @Bean
  15. public Object retryInterceptor(Retryer retryer) throws Exception {
  16. ExceptionClassifierRetryPolicy policy = new ExceptionClassifierRetryPolicy();
  17. policy.setPolicyMap(Map.of(
  18. IllegalStateException.class, new SimpleRetryPolicy(2),
  19. IllegalArgumentException.class, new SimpleRetryPolicy(3)));
  20. Method recover = retryer.getClass().getDeclaredMethod("recover", Exception.class);
  21. return RetryInterceptorBuilder.stateless()
  22. .retryPolicy(policy)
  23. .backOffOptions(1_000, 1.5, 10_000)
  24. .recoverer(new RecoverAnnotationRecoveryHandler<>(retryer, recover))
  25. .build();
  26. }
  27. }
  28. @Component
  29. class Retryer {
  30. @Retryable(interceptor = "retryInterceptor")
  31. public void toRetry(String in) {
  32. System.out.println(in);
  33. if ("state".equals(in)) {
  34. throw new IllegalStateException();
  35. }
  36. else {
  37. throw new IllegalArgumentException();
  38. }
  39. }
  40. @Recover
  41. public void recover(Exception ex) {
  42. System.out.println("Recovered from " + ex
  43. + ", retry count:" + RetrySynchronizationManager.getContext().getRetryCount());
  44. }
  45. }
  1. state
  2. state
  3. Recovered from java.lang.IllegalStateException, retry count:2
  4. arg
  5. arg
  6. arg
  7. 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:

  1. @SpringBootApplication
  2. @EnableRetry
  3. public class So64029544Application {
  4. public static void main(String[] args) {
  5. SpringApplication.run(So64029544Application.class, args);
  6. }
  7. @Bean
  8. public ApplicationRunner runner(Retryer retryer) {
  9. return args -&gt; {
  10. retryer.toRetry(&quot;state&quot;);
  11. retryer.toRetry(&quot;arg&quot;);
  12. };
  13. }
  14. @Bean
  15. public Object retryInterceptor(Retryer retryer) throws Exception {
  16. ExceptionClassifierRetryPolicy policy = new ExceptionClassifierRetryPolicy();
  17. policy.setPolicyMap(Map.of(
  18. IllegalStateException.class, new SimpleRetryPolicy(2),
  19. IllegalArgumentException.class, new SimpleRetryPolicy(3)));
  20. Method recover = retryer.getClass().getDeclaredMethod(&quot;recover&quot;, Exception.class);
  21. return RetryInterceptorBuilder.stateless()
  22. .retryPolicy(policy)
  23. .backOffOptions(1_000, 1.5, 10_000)
  24. .recoverer(new RecoverAnnotationRecoveryHandler&lt;&gt;(retryer, recover))
  25. .build();
  26. }
  27. }
  28. @Component
  29. class Retryer {
  30. @Retryable(interceptor = &quot;retryInterceptor&quot;)
  31. public void toRetry(String in) {
  32. System.out.println(in);
  33. if (&quot;state&quot;.equals(in)) {
  34. throw new IllegalStateException();
  35. }
  36. else {
  37. throw new IllegalArgumentException();
  38. }
  39. }
  40. @Recover
  41. public void recover(Exception ex) {
  42. System.out.println(&quot;Recovered from &quot; + ex
  43. + &quot;, retry count:&quot; + RetrySynchronizationManager.getContext().getRetryCount());
  44. }
  45. }
  1. state
  2. state
  3. Recovered from java.lang.IllegalStateException, retry count:2
  4. arg
  5. arg
  6. arg
  7. Recovered from java.lang.IllegalArgumentException, retry count:3

huangapple
  • 本文由 发表于 2020年9月23日 21:54:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/64029544.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定