org.projectlombok lombok
org.aspectj aspectjweaver 1.9.6
org.springframework.retry spring-retry 1.2.5.RELEASE
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;@SpringBootApplication
@EnableRetry
public class DemoApplication {public static void main(String[] args) {SpringApplication.run (DemoApplication.class, args);}}
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;import java.util.concurrent.atomic.LongAdder;@Component
@Slf4j
public class RetryServcie {private LongAdder num = new LongAdder ();/*** @return java.lang.String* @Desc 模拟服务调用异常* @Author xiaoding* @date 2022/11/23 17.51*/@Retryable(value = {RuntimeException.class}, maxAttemptsExpression = "${retry.maxAttempts:2}",backoff = @Backoff(delayExpression = "${retry.backoff:1000}"))public String hello() {num.increment ();long l = num.longValue ();if (l < 3L) {throw new RuntimeException ("出错了哟!");} else {num.reset ();return "接口调用成功";}}// 重试完成后 还是不成功的情况下,会执行被 @Recover修饰的方法。@Recoverpublic String recover(RuntimeException t) {log.info ("RetryServcie.recover:{}", t.getClass ().getName ());return "失败了";}
}
@Retryable 修饰在要重试的方法上,有以下参数:
interceptor:重试拦截器bean名称,用于可重试方法;value:可重试的异常类型。含义同 include。默认为空(如果excludes也为空,则重试所有异常);include:可重试的异常类型。默认为空(如果excludes也为空,则重试所有异常);exclude:无需重试的异常类型。默认为空(如果includes也为空,则重试所有异常);label:统计报告的唯一标签。如果未提供,则调用者可以选择忽略它或提供一个默认值;stateful:若为true,标志重试是有状态的:即重新抛出异常,但是重试策略与相同的策略应用于具有相同参数的后续调用。若为false,则不会重新引发可重试的异常;maxAttempts:最大重试次数(包括第一次失败),默认为3次;maxAttemptsExpression:计算最大尝试次数(包括第一次失败)的表达式,默认为3 次;backoff:重试等待策略;exceptionExpression:指定在RetryServcie.canRetry()返回true之后要求值的表达式-可用于有条件地禁止重试。@Backoff,重试等待策略。有以下参数:
value:倒退时期;delay:重试之间的等待时间(以毫秒为单位);maxDelay:重试之间的最大等待时间(以毫秒为单位);multiplier:指定延迟的倍数;delayExpression:重试之间的等待时间表达式;maxDelayExpression:重试之间的最大等待时间表达式;multiplierExpression:指定延迟的倍数表达式;random:随机指定延迟时间。当重试耗尽时,用于@Retryable重试失败后处理方法,此方法里的异常一定要是 @Retryable方法里抛出的异常,否则不会调用这个方法。
@Retryable和@Recover修饰的方法要在同一个类中,且被@Recover 标记的方法的返回值必须与@Retryable方法一致,方法的第一个参数,必须是Throwable类型的,建议是与@Retryable 配置的异常一致,其他的参数,需要与 @Retryable 方法的参数一致。
由于@Retryable注解是通过切面实现的,因此要避免@Retryable 注解的方法的调用方和被调用方处于同一个类中,因为这样会使@Retryable 注解失效。
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/retry")
@Slf4j
public class RetryController {@Autowiredprivate RetryServcie retryServcie;@GetMapping(value = "/test")public Result retry() {String hello;hello = retryServcie.hello ();return Result.ok ().setData (hello);}
}@Data
@Accessors(chain = true)
class Result {private int code;private String message;private Object data;public static Result ok() {return new Result ();}
}