spring-retry

springboot集成spring-retry框架

1.加入依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>

2.在主类上加上@EnableRetry注解,表示启用重试机制

1
2
3
4
5
6
7
@SpringBootApplication
@EnableRetry
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}

3.定义一个简单的controller层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
public class HelloController {
Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private PayService payService;

@GetMapping("/createOrder")
public String createOrder(@RequestParam int num) throws Exception{
int remainingnum = payService.minGoodsnum(num == 0 ? 1: num);
logger.info("剩余的数量==="+remainingnum);
return "库库存成功";
}

}

4.在controller中调用减库存的service接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service
public class PayService {
private Logger logger = LoggerFactory.getLogger(getClass());
private final int totalNum = 100000;

@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
public int minGoodsnum(int num) throws Exception{
logger.info("minGoodsnum开始"+ LocalTime.now());
if(num <= 0){
throw new Exception("数量不对");
}
logger.info("minGoodsnum执行结束");
return totalNum - num;
}
}

注解及参数说明

1
2
3
4
5
6
7
8
9
10
11
12
注解说明:
@Retryable:标注此注解的方法在发生异常时会进行重试
@Recover:用于@Retryable重试失败后处理方法,此方法里的异常一定要是@Retryable方法里抛出的异常,否则不会调用这个方法
参数说明:
value: 抛出指定异常才会重试,可以抛出该异常子类
include:和value一样,默认为空,当exclude也为空时,默认所有异常
exclude:指定不处理的异常
maxAttempts:最大重试次数,默认3
backoff:重试等待策略,默认使用@Backoff@Backoff的value默认为1000L,multiplier(指定延迟倍数,默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为2,则第一次重试为1秒,第二次为2秒,第三次为4秒)
delay表示重试的延迟时间:单位为毫秒,默认10001秒)
multiplier表示下一次延时时间是这一次的倍数,默认为0,表示忽略
比如第一次延迟时间为2s,multiplier为1.5时,第二次延迟时间为2*1.5=3s,第三次延迟时间为3*1.5=4.5s

5.默认情况重试三次抛出异常,可使用@Recover注解,当重试次数达到设置的次数的时候,执行的回调函数。(此时不会再抛出异常)

1
2
3
4
5
6
7
和minGoodsnum定义在一个类中
@Recover
public int recover(Exception e) {
logger.warn("减库存失败!!!" + LocalTime.now() + e.getMessage());
//记日志到数据库
return totalNum;
}

6.测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
a.采用http接口
@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 1.5))

正常情况:http://localhost:8080/createOrder?num=10
减库存开始13:53:42.470
减库存执行结束13:53:42.471
剩余的数量===99990

异常情况: http://localhost:8080/createOrder?num=-1
减库存开始13:54:09.691
减库存开始13:54:11.691
减库存开始13:54:14.693
减库存开始13:54:19.194
减库存开始13:54:25.944
减库存失败!!!13:54:25.944数量不对
剩余的数量===99990



@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000))
正常情况:http://localhost:8080/createOrder?num=10
减库存开始14:03:02.009
减库存执行结束14:03:02.009
剩余的数量===99990

异常情况: http://localhost:8080/createOrder?num=-1
减库存开始14:03:05.217
减库存开始14:03:07.218
减库存开始14:03:09.218
减库存开始14:03:11.218
减库存开始14:03:13.227
减库存失败!!!14:03:13.228数量不对
剩余的数量===99990


b.采用junit测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootRetryApplicationTests {

@Autowired
private PayService payService;

@Test
public void payTest() throws Exception {
int store = payService.minGoodsnum(-1);
System.out.println("库存为:" + store);
}

}

减库存开始14:18:09.657
减库存开始14:18:11.659
减库存开始14:18:13.660
减库存开始14:18:15.661
减库存开始14:18:17.662
减库存失败!!!14:18:17.666数量不对