Spring Retry 是 Spring 中提供的实现重试功能的组件。
可以使用基于注解的方式实现,也可以使用基于RetryTemplate的编程方式实现。
本例使用基于注解的方法
主要使用的注解
@EnableRetry:修饰启动类
@Retryable:修饰需要重试的方法
常用的属性:
value,指定需要重试的异常,和include属性作用一样
maxAttempts,指定重试次数,包含第一次调用
maxAttemptsExpression,指定设置重试次数的表达式,比如可以读取配置文件中设置的重试次数,使用该属性后maxAttempts属性失效
backoff,设置退避策略
@Backoff:设置重试的退避策略
该注解常用的属性:
delay,重试的延迟时间
multiplier,延迟时间的乘数因子
@Recover:修饰恢复方法,恢复方法必须与@Retryable方法在同一个类中,恢复方法的参数和返回值类型可以和重试方法的返回类型和参数列表一致。
恢复方法的参数还可以使用异常对象,恢复方法也可以不写参数。
如果重试失败,我们可以考虑在该方法中将数据写入补偿表,通过定时任务扫描补偿表进行补偿处理。
导入jar
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<!-- retry组件需要使用面向切面的一些jar -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
业务层
package com.qfedu.springbootretry.service;
import com.alibaba.fastjson.JSON;
import com.qfedu.springbootretry.param.PointParam;
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.Service;
@Slf4j
@Service
public class PointServiceImpl implements PointService {
@Retryable(value = {RuntimeException.class}, maxAttempts = 4, maxAttemptsExpression = "${retry.times}", backoff = @Backoff(delay = 2000, multiplier = 2))
@Override
public void addPoint(PointParam pointParam) {
log.info("add point:{}", JSON.toJSONString(pointParam));
throw new RuntimeException("add point failed");
}
// 参数可以不写
@Recover
private void recover(RuntimeException e, PointParam pointParam) {
log.info("recover: {},数据写入补偿表", JSON.toJSONString(pointParam));
}
}
注意:根据本例backoff配置,表示重试初始延迟2秒,以后再延迟时,延迟时间是上次延迟时间的2倍
控制层
package com.qfedu.springbootretry.controller;
import com.qfedu.springbootretry.param.PointParam;
import com.qfedu.springbootretry.service.PointService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class PointController {
@Resource
private PointService pointService;
@GetMapping("/point/add")
public String addPoint(PointParam param) {
System.out.println("haha");
new Thread(() -> {
pointService.addPoint(param);
}).start();
// pointService.addPoint(param);
return "success";
}
}
配置文件
# 应用服务 WEB 访问端口
server.port=8080
# 重试次数
retry.times=5
启动类
package com.qfedu.springbootretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@EnableRetry
@SpringBootApplication
public class SpringbootRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRetryApplication.class, args);
}
}
测试结果

由于配置了maxAttemptsExpression,maxAttempts失效,根据backoff配置,第二次重试延迟2秒,第三次延迟4秒,第四次延迟8表,第五次延迟16秒
2439

被折叠的 条评论
为什么被折叠?



