如果@Retryable returns 一个值,@Recover 不起作用
@Recover is not working if @Retryable returns a value
我正在尝试实现重试逻辑。我的代码按预期工作,直到 return 类型的重试方法无效。当我将其更改为 String 时,@Recover 停止工作。
@Component
public class AdapterImpl {
int count = 0;
@Retryable(include = {NullPointerException.class, IllegalStateException.class}, backoff = @Backoff(delay = 100, maxDelay = 101), maxAttempts = 5)
public void retry(String foo) {
System.out.println(foo + " " + count++);
if (foo.equals("foo")) {
throw new NullPointerException("foo");
} else if (foo.equals("bar")) {
throw new IllegalStateException("bar");
}
// return "hi";
}
@Recover
public void connectionException(NullPointerException e) {
System.out.println("Retry failure NullPointerException");
}
@Recover
public void connectionException(IllegalStateException e) {
System.out.println("Retry failure IllegalStateException");
}
}
对于 foo 和 bar,重试逻辑都有效。日志如下
bar 0
bar 1
bar 2
bar 3
bar 4
Retry failure IllegalStateException
但是当我将 return 类型的重试方法更改为 String 时,@Recover 方法停止工作。
@Retryable(include = {NullPointerException.class, IllegalStateException.class}, backoff = @Backoff(delay = 100, maxDelay = 101), maxAttempts = 5)
public String retry(String foo) {
System.out.println(foo + " " + count++);
if (foo.equals("foo")) {
throw new NullPointerException("foo");
} else if (foo.equals("bar")) {
throw new IllegalStateException("bar");
}
return "hi";
}
日志如下
bar 0
bar 1
bar 2
bar 3
bar 4
2020-04-26 23:28:30.800 ERROR 59644 --- [nio-8087-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.IllegalStateException: bar] with root cause
java.lang.IllegalStateException: bar
我的build.gradle是
plugins {
id 'java'
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
group 'com.demo.web'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.retry:spring-retry'
compile 'org.springframework:spring-aspects'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
我做错了什么?
有一定的使用规则@Recover with spring @Retryable
- 作为恢复处理程序的方法调用的注释。
- 一个合适的恢复处理程序有一个 Throwable 类型(或 Throwable 的子类型)的第一个参数和一个与要从中恢复的 @Retryable 方法相同类型的 return 值。
- Throwable 的第一个参数是可选的(但是没有它的方法只有在没有其他匹配的情况下才会被调用)。
- 后续参数从失败方法的参数列表中按顺序填充。
因此请确保您拥有与上述规则匹配的可恢复方法
@Recover
public String connectionException(NullPointerException e, String foo) {
System.out.println("Retry failure NullPointerException");
}
@Recover
public String connectionException(IllegalStateException e, String foo) {
System.out.println("Retry failure IllegalStateException");
}
我正在尝试实现重试逻辑。我的代码按预期工作,直到 return 类型的重试方法无效。当我将其更改为 String 时,@Recover 停止工作。
@Component
public class AdapterImpl {
int count = 0;
@Retryable(include = {NullPointerException.class, IllegalStateException.class}, backoff = @Backoff(delay = 100, maxDelay = 101), maxAttempts = 5)
public void retry(String foo) {
System.out.println(foo + " " + count++);
if (foo.equals("foo")) {
throw new NullPointerException("foo");
} else if (foo.equals("bar")) {
throw new IllegalStateException("bar");
}
// return "hi";
}
@Recover
public void connectionException(NullPointerException e) {
System.out.println("Retry failure NullPointerException");
}
@Recover
public void connectionException(IllegalStateException e) {
System.out.println("Retry failure IllegalStateException");
}
}
对于 foo 和 bar,重试逻辑都有效。日志如下
bar 0
bar 1
bar 2
bar 3
bar 4
Retry failure IllegalStateException
但是当我将 return 类型的重试方法更改为 String 时,@Recover 方法停止工作。
@Retryable(include = {NullPointerException.class, IllegalStateException.class}, backoff = @Backoff(delay = 100, maxDelay = 101), maxAttempts = 5)
public String retry(String foo) {
System.out.println(foo + " " + count++);
if (foo.equals("foo")) {
throw new NullPointerException("foo");
} else if (foo.equals("bar")) {
throw new IllegalStateException("bar");
}
return "hi";
}
日志如下
bar 0
bar 1
bar 2
bar 3
bar 4
2020-04-26 23:28:30.800 ERROR 59644 --- [nio-8087-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.IllegalStateException: bar] with root cause
java.lang.IllegalStateException: bar
我的build.gradle是
plugins {
id 'java'
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
group 'com.demo.web'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.retry:spring-retry'
compile 'org.springframework:spring-aspects'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
我做错了什么?
有一定的使用规则@Recover with spring @Retryable
- 作为恢复处理程序的方法调用的注释。
- 一个合适的恢复处理程序有一个 Throwable 类型(或 Throwable 的子类型)的第一个参数和一个与要从中恢复的 @Retryable 方法相同类型的 return 值。
- Throwable 的第一个参数是可选的(但是没有它的方法只有在没有其他匹配的情况下才会被调用)。
- 后续参数从失败方法的参数列表中按顺序填充。
因此请确保您拥有与上述规则匹配的可恢复方法
@Recover
public String connectionException(NullPointerException e, String foo) {
System.out.println("Retry failure NullPointerException");
}
@Recover
public String connectionException(IllegalStateException e, String foo) {
System.out.println("Retry failure IllegalStateException");
}