[英]Spring Retry: method annotated with @Recover not being called
我正在測試 spring 重試,但似乎沒有調用恢復。 試圖讓它工作,但它似乎詳盡無遺。 我沒有參數傳遞給@Recover,Throwable,Exception。 更改了重試依賴版本,它似乎包含在 spring 引導的 aop 中並將其刪除。 沒有通過以下異常消息調用保持恢復。
請求處理失敗; 嵌套異常是 org.springframework.retry.ExhaustedRetryException: 找不到恢復方法; 嵌套異常是 java.lang.ArithmeticException: / by zero] 根本原因
任何幫助將非常感激
我的代碼如下所示。
配置 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);
}
};
}
}
Rest Controller 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及多種arguments
@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");
}
}
控制台的屏幕截圖
我終於得到了答案。
對於要調用的帶有 @Recover 注釋的方法,它必須具有相同的方法參數(加上異常)和相同的返回類型。
我使用不同類型的異常參數對其進行了測試,如果它們具有更具體的異常類型,則會調用方法。 如果我有一個這樣的方法將被調用而不是一個帶有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";
}
您應該使用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
失敗時運行特殊的恢復代碼。
您可以參考更多關於 如何使用 Spring-Retry 處理重試?
編輯
基於最新的異常,嘗試提供 spring-retry 版本
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
@Recover 方法應該具有與您正在為其編寫重試方法的原始方法相同的返回類型和拋出的異常。
@Recover public String connectionException(RetryException e) throws RetryException { return e.getMessage(); }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.