Spring 重试:未调用带有 @Recover 注释的方法
Spring Retry: method annotated with @Recover not being called
我正在测试 spring 重试,但似乎没有调用恢复。试图让它工作,但它似乎详尽无遗。我没有参数、Throwable、Exception 传递给@Recover。更改了重试依赖版本,它似乎包含在用于 spring 引导的 aop 中,并将其删除。保持恢复未被调用并出现以下异常消息。
Request processing failed; nested exception is
org.springframework.retry.ExhaustedRetryException: Cannot locate
recovery method; nested exception is java.lang.ArithmeticException: /
by zero] with root cause
如有任何帮助,我们将不胜感激
我的代码如下所示。
配置class
package hello;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
@SpringBootApplication
@EnableRetry
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by `Spring Boot:");`
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
休息控制器class;
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
@Autowired
private SomeService service;
@RequestMapping("/")
public String hello() {
String result = service.getInfo();
return result;
}
}
服务 class 是 ;
package hello;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class SomeService {
@Retryable(value = ArithmeticException.class, maxAttempts = 3, `backoff = @Backoff(delay = 3000))`
public String getInfo() {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
}
@Recover
public void helpHere(ArithmeticException cause) {
System.out.println(cause);
System.out.println("Recovery place!");
}
}
这是我的依赖项列表
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- tag::actuator[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- end::actuator[] -->
<!-- tag::tests[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- end::tests[] -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
有 try-catch 和各种参数
@Service
public class SomeService {
@Retryable(value = {ArithmeticException.class}, maxAttempts = 3, `backoff = @Backoff(delay = 3000))`
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
} catch(ArithmeticException ex) {
System.out.println("In the arthemetic Exception");
throw new ArithmeticException();
}
}
@Recover
public void helpHere(ArithmeticException cause) {
System.out.println(cause);
System.out.println("Recovery place! ArithmeticException");
}
@Recover
public void helpHere(Exception cause ) {
System.out.println(cause);
System.out.println("Recovery place! Exception");
}
@Recover
public void helpHere(Throwable cause) {
System.out.println(cause);
System.out.println("Recovery place! Exception");
}
@Recover
public void helpHere() {
System.out.println("Recovery place! Exception");
}
}
控制台的屏幕截图
你应该使用try-catch
来处理它。这里的例子
@Retryable(value = ArithmeticException.class, maxAttempts = 5, backoff = @Backoff(delay = 3000))
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4 / 0;
} catch (ArithmeticException ex) {
// will be retried
throw ex;
}
}
throw ex;
是必须的,因为它告诉 Spring 应用重试处理。
使用 @Recover
我们为 ArithmeticException
定义了一个单独的恢复方法。这允许我们在可重试方法因 ArithmeticException
.
失败时 运行 特殊恢复代码
您可以参考更多 How to handle retry with Spring-Retry ?
编辑
根据最新异常,尝试提供版本spring-retry
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
我终于得到了答案。
要调用使用 @Recover 注释的方法,它必须具有相同的方法参数(加上异常)和相同的 return 类型。
我用不同类型的异常参数测试了它,如果它们有更具体的异常类型,就会调用方法。如果我有一个这样的方法,将比带有 Exception
参数的方法被调用。但是,如果我有多个恢复方法,将只调用一个具有更具体异常参数的方法。
@Recover
public String helpHere(ArithmeticException cause) {
最终代码示例
package hello;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class SomeService {
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 3000))
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
} catch(Exception ex) {
System.out.println("In the arthemetic Exception");
throw new ArithmeticException();
}
}
@Recover
public String helpHere(ArithmeticException cause) {
System.out.println("Recovery place! ArithmeticException");
return "Hello";
}
@Recover
public String helpHere(Exception cause ) {
System.out.println("Recovery place! Exception");
return "Hello";
}
@Recover
public String helpHere() {
System.out.println("Recovery place! Exception");
return "Hello";
}
@Recover
public String helpHere(Throwable cause) {
System.out.println("Recovery place! Throwable");
return "Hello";
}
我正在测试 spring 重试,但似乎没有调用恢复。试图让它工作,但它似乎详尽无遗。我没有参数、Throwable、Exception 传递给@Recover。更改了重试依赖版本,它似乎包含在用于 spring 引导的 aop 中,并将其删除。保持恢复未被调用并出现以下异常消息。
Request processing failed; nested exception is org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.ArithmeticException: / by zero] with root cause
如有任何帮助,我们将不胜感激
我的代码如下所示。
配置class
package hello;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
@SpringBootApplication
@EnableRetry
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by `Spring Boot:");`
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
休息控制器class;
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
@Autowired
private SomeService service;
@RequestMapping("/")
public String hello() {
String result = service.getInfo();
return result;
}
}
服务 class 是 ;
package hello;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class SomeService {
@Retryable(value = ArithmeticException.class, maxAttempts = 3, `backoff = @Backoff(delay = 3000))`
public String getInfo() {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
}
@Recover
public void helpHere(ArithmeticException cause) {
System.out.println(cause);
System.out.println("Recovery place!");
}
}
这是我的依赖项列表
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- tag::actuator[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- end::actuator[] -->
<!-- tag::tests[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- end::tests[] -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
有 try-catch 和各种参数
@Service
public class SomeService {
@Retryable(value = {ArithmeticException.class}, maxAttempts = 3, `backoff = @Backoff(delay = 3000))`
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
} catch(ArithmeticException ex) {
System.out.println("In the arthemetic Exception");
throw new ArithmeticException();
}
}
@Recover
public void helpHere(ArithmeticException cause) {
System.out.println(cause);
System.out.println("Recovery place! ArithmeticException");
}
@Recover
public void helpHere(Exception cause ) {
System.out.println(cause);
System.out.println("Recovery place! Exception");
}
@Recover
public void helpHere(Throwable cause) {
System.out.println(cause);
System.out.println("Recovery place! Exception");
}
@Recover
public void helpHere() {
System.out.println("Recovery place! Exception");
}
}
控制台的屏幕截图
你应该使用try-catch
来处理它。这里的例子
@Retryable(value = ArithmeticException.class, maxAttempts = 5, backoff = @Backoff(delay = 3000))
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4 / 0;
} catch (ArithmeticException ex) {
// will be retried
throw ex;
}
}
throw ex;
是必须的,因为它告诉 Spring 应用重试处理。
使用 @Recover
我们为 ArithmeticException
定义了一个单独的恢复方法。这允许我们在可重试方法因 ArithmeticException
.
您可以参考更多 How to handle retry with Spring-Retry ?
编辑
根据最新异常,尝试提供版本spring-retry
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
我终于得到了答案。
要调用使用 @Recover 注释的方法,它必须具有相同的方法参数(加上异常)和相同的 return 类型。
我用不同类型的异常参数测试了它,如果它们有更具体的异常类型,就会调用方法。如果我有一个这样的方法,将比带有 Exception
参数的方法被调用。但是,如果我有多个恢复方法,将只调用一个具有更具体异常参数的方法。
@Recover
public String helpHere(ArithmeticException cause) {
最终代码示例
package hello;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class SomeService {
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 3000))
public String getInfo() {
try {
System.out.println("How many time will this be printed?");
return "Hello" + 4/0;
} catch(Exception ex) {
System.out.println("In the arthemetic Exception");
throw new ArithmeticException();
}
}
@Recover
public String helpHere(ArithmeticException cause) {
System.out.println("Recovery place! ArithmeticException");
return "Hello";
}
@Recover
public String helpHere(Exception cause ) {
System.out.println("Recovery place! Exception");
return "Hello";
}
@Recover
public String helpHere() {
System.out.println("Recovery place! Exception");
return "Hello";
}
@Recover
public String helpHere(Throwable cause) {
System.out.println("Recovery place! Throwable");
return "Hello";
}