软件编程
位置:首页>> 软件编程>> java编程>> 浅谈spring的重试机制无效@Retryable@EnableRetry

浅谈spring的重试机制无效@Retryable@EnableRetry

作者:Singlerr  发布时间:2021-12-12 10:42:57 

标签:spring,重试,@Retryable,@EnableRetry

spring-retry模块支持方法和类、接口、枚举级别的重试

方式很简单,引入pom包


<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>lastest</version>
</parent>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
 <groupId>org.springframework.retry</groupId>
 <artifactId>spring-retry</artifactId>
 <version>1.1.2.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.8.6</version>
</dependency>

然后在@Configuration注解的类中添加@EnableRetry

最后在想要重试的方法上添加@Retryable(Exception.class)

由于retry用到了aspect增强,所有会有aspect的坑,就是方法内部调用,会使aspect增强失效,那么retry当然也会失效。

例如


public class demo {
 public void A() {
   B();
 }

@Retryable(Exception.class)
 public void B() {
   throw new RuntimeException("retry...");
 }
}

这种情况B()不会重试。

补充知识:Springboot整合Spring Retry实现重试机制

在项目开发过程中,经常会有这样的情况:第一次执行一个操作不成功,考虑到可能是网络原因造成,就多执行几次操作,直到得到想要的结果为止,这就是重试机制。

Springboot可以通过整合Spring Retry框架实现重试。

下面讲一下在之前新建的ibatis项目基础上整合Spring Retry框架的步骤:

1、首先要在pom.xml配置中加入spring-retry的依赖:


<dependency>
 <groupId>org.springframework.retry</groupId>
 <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
</dependency>

2、在启动类中加入重试注解@EnableRetry。


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;

@EnableRetry //重试注解
@MapperScan("com.batis.mapper")
@SpringBootApplication
public class BatisApplication {
 public static void main(String[] args) {
   SpringApplication.run(BatisApplication.class, args);
 }
}

3、新建重试接口RetryService和实现类RetryServiceImpl

重试接口:


public interface RetryService {
 void retryTransferAccounts(int fromAccountId, int toAccountId, float money) throws Exception;
}

接口实现类:


import com.batis.mapper.AccountMapper;
import com.batis.model.Account;
import com.batis.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class RetryServiceImpl implements RetryService {
 @Autowired
 private AccountMapper accountMapper;

@Transactional
 @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 3000, multiplier = 1, maxDelay = 10000))
 @Override
 public void retryTransferAccounts(int fromAccountId, int toAccountId, float money) throws Exception {
   Account fromAccount = accountMapper.findOne(fromAccountId);
   fromAccount.setBalance(fromAccount.getBalance() - money);
   accountMapper.update(fromAccount);

int a = 2 / 0;
   Account toAccount = accountMapper.findOne(toAccountId);
   toAccount.setBalance(toAccount.getBalance() + money);
   accountMapper.update(toAccount);
   throw new Exception();
 }

@Recover
 public void recover(Exception e) {
   System.out.println("回调方法执行!!!");
 }
}

@Retryable:标记当前方法会使用重试机制

value:重试的触发机制,当遇到Exception异常的时候,会触发重试

maxAttempts:重试次数(包括第一次调用)

delay:重试的间隔时间

multiplier:delay时间的间隔倍数

maxDelay:重试次数之间的最大时间间隔,默认为0,如果小于delay的设置,则默认为30000L

@Recover:标记方法为回调方法,传参与@Retryable的value值需一致

4、新建重试控制器类RetryController


import com.batis.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/retry")
public class RetryController {
 @Autowired
 private RetryService retryService;

@RequestMapping(value = "/transfer", method = RequestMethod.GET)
 public String transferAccounts() {
   try {
     retryService.retryTransferAccounts(1, 2, 200);
     return "ok";
   } catch (Exception e) {
     return "no";
   }
 }
}

5、启动ibatis项目进行测试,在浏览器地址栏输入:http://localhost:8080/retry/transfer

浅谈spring的重试机制无效@Retryable@EnableRetry

可以看到,转账操作一共执行了3次,最后执行了回调方法。

至此Springboot整合Spring Retry的步骤已经完成,测试也非常成功!

有可以改进的地方希望诸位同学不要吝惜笔墨,加以指正,万分感谢!

来源:https://blog.csdn.net/xsgnzb/article/details/78780795

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com