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

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

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 -&gt; {
			retryer.toRetry(&quot;state&quot;);
			retryer.toRetry(&quot;arg&quot;);
		};
	}

	@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(&quot;recover&quot;, Exception.class);
		return RetryInterceptorBuilder.stateless()
				.retryPolicy(policy)
				.backOffOptions(1_000, 1.5, 10_000)
				.recoverer(new RecoverAnnotationRecoveryHandler&lt;&gt;(retryer, recover))
				.build();
	}
}

@Component
class Retryer {

	@Retryable(interceptor = &quot;retryInterceptor&quot;)
	public void toRetry(String in) {
		System.out.println(in);
		if (&quot;state&quot;.equals(in)) {
			throw new IllegalStateException();
		}
		else {
			throw new IllegalArgumentException();
		}
	}

	@Recover
	public void recover(Exception ex) {
		System.out.println(&quot;Recovered from &quot; + ex
				+ &quot;, retry count:&quot; + RetrySynchronizationManager.getContext().getRetryCount());
	}

}
state
state
Recovered from java.lang.IllegalStateException, retry count:2
arg
arg
arg
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:

确定