Spring Retry重试框架的应用

导读:本篇文章讲解 Spring Retry重试框架的应用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

环境:SpringBoot2.4.3 + Spring Retry + JPA + MySQL + JDK8


  • 相关依赖
<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
  • 配置文件
spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/testjpa?serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: ******
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimumIdle: 10
      maximumPoolSize: 200
      autoCommit: true
      idleTimeout: 30000
      poolName: MasterDatabookHikariCP
      maxLifetime: 1800000
      connectionTimeout: 30000
      connectionTestQuery: SELECT 1
  • 实体类及DAO
@Entity
@Table(name = "t_account")
public class Account {
    @Id
    private Long id;
    private String userId;
    private BigDecimal money;
}
public interface AccountDAO extends JpaRepository<Account, Long> {

    Account findByUserId(String userId);

}
  • Service类
@Service
public class AccountService {
	
	@Resource
	private AccountDAO accountDAO ;
	
	@Transactional
	@Retryable(value = {InvalidParameterException.class})
	public Account save(Account account) {
		System.out.println(Thread.currentThread().getName()) ;
		if (account.getId() == 0) {
			System.out.println("save retry...") ;
			throw new InvalidParameterException("无效参数") ;
		}
		return accountDAO.saveAndFlush(account) ;
	}
  // 当重试了指定的次数后将会回调此方法
	@Recover
    public Account recoverSave(Exception e) {
		System.out.println("............." + e.getMessage()) ;
		return null ;
    }
	
}

@Retryable注解说明:

  • recover:指定兜底/补偿的方法名。如果不指定,默认对照 @Recover 标识的,第一入参为重试异常,其余入参和出参一致的方法;这里是通过@Recover注解对照指定。
  • interceptor:指定方法切面 bean,org.aopalliance.intercept.MethodInterceptor 实现类
  • value / include:可重试的异常类型,如果value和include都为空,那么会对所有的异常进行重试;
  • exclude:和 include 相反,指出哪些异常不需要重试;
  • label:可以指定唯一标签,用于统计;
  • stateful:默认false。重试是否是有状态的;
  • maxAttempts:最大的重试次数,默认为3;
  • backoff:指定 @Backoff,回退策略;@Backoff属性如下:

Spring Retry重试框架的应用

 

这里可以指定重试的策略,比如:延迟多久进行重试。

  • listeners:监听器,指定 org.springframework.retry.RetryListener 实现 bean。下面有示例演示。

开启重试功能@EnableRetry

@Configuration
@EnableRetry
public class RetryConfig {
	
}

测试:

@Resource
	private AccountService accountService ;
	
	@Test
	public void testSave() {
		Account account = new Account() ;
		account.setId(0L) ;
		account.setMoney(BigDecimal.valueOf(1000)) ;
		account.setUserId("1") ;
		
		accountService.save(account) ;
	}

控制台输出:

Spring Retry重试框架的应用

 

默认进行了3次重试。


@Retryable注解属性listeners的使用

@Retryable(value = {InvalidParameterException.class}, stateful = false, listeners = {“accountRetryListener”})

定义监听器:

public class AccountRetryListener implements RetryListener {

	@Override
	public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
		System.out.println("open invoke...") ;
		return false;
	}

	@Override
	public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
			Throwable throwable) {
		System.out.println("close invoke...") ;
	}

	@Override
	public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
			Throwable throwable) {
		System.out.println("onError invoke...") ;
		throwable.getStackTrace() ;
	}

}

这里的open方法如果返回false,那么将不会进行重试。

执行结果:

Spring Retry重试框架的应用

 

 


基于编程式重试

自定义RetryTemplate

@Configuration
@EnableRetry
public class RetryConfig {
	
	@Bean
	public RetryTemplate retryTemplate() {
		RetryTemplate template = RetryTemplate.builder()
				.maxAttempts(3) // 重试次数
				.fixedBackoff(1000) // 以固定的时间间隔重试(1000ms)
				.retryOn(InvalidParameterException.class) // 当发生InvalidParameterException异常时进行重试
				.build();
		return template ;
	}
	
}
public class AccountService {
	
	@Resource
	private AccountDAO accountDAO ;
	@Resource
	private RetryTemplate retryTemplate ;
	
	@Transactional
	public Account update(Account account) {
		return retryTemplate.execute(context -> {
			if (account.getId() == 0) {
				System.out.println("update retry...") ;
				throw new InvalidParameterException("无效参数") ;
			}
			return accountDAO.saveAndFlush(account) ;
		}, context -> {
      System.out.println("重试结束...") ;
			return null ;
		}) ;
	}
	
}

测试:

@Test
	public void testUpdate() {
		Account account = new Account() ;
		account.setId(0L) ;
		account.setMoney(BigDecimal.valueOf(1000)) ;
		account.setUserId("1") ;
		
		accountService.update(account) ;
	}

执行结果

Spring Retry重试框架的应用

 

完毕!!!

给个关注+转发呗,谢谢

Spring Retry重试框架的应用

ElasticSearch使用Java API调用相关服务

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80022.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!