Java重试机制

在项目开发过程中,经常会有这样的情况:第一次执行一个操作不成功,考虑到可能是网络原因造成,就多执行几次操作,直到得到想要的结果为止,这就是重试机制。
Springboot可以通过整合Spring Retry框架实现重试。
下面讲一下整合Spring Retry框架的步骤:

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

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

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


@EnableRetry
@SpringBootApplication
public class ServerMain {
	
	public static void main(String[] args) {
        SpringApplication.run(ServerMain.class, args);
    }
	
}

3、新建重试接口RetryService

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

/**  
 * @Title:  RetryService.java   
 * @Package com.skd.modules.retry   
 * @Description:    TODO(重试接口)   
 * @ImportantNotes:
 */

@Service
public class RetryService {
	
	private final static Logger logger = LoggerFactory.getLogger(RetryService.class);
	
	private final int totalNum = 100000;
	 
    /**
     * @Retryable的参数说明: •value:抛出指定异常才会重试
     * •include:和value一样,默认为空,当exclude也为空时,默认所以异常
     * •exclude:指定不处理的异常
     * •maxAttempts:最大重试次数,默认3次
     * •backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
     */
    @Retryable(value = IllegalArgumentException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
    public int retry(int num) {
        logger.info("减库存({})开始" + LocalTime.now(),totalNum);
        // do something
        
        if (num <= 0) {
            throw new IllegalArgumentException("数量不对");
        }
        logger.info("减库存执行结束" + LocalTime.now());
        return totalNum - num;
    }
 
    @Recover
    public int recover(IllegalArgumentException e) {
        logger.warn("减库存失败!!!" + LocalTime.now());
        return totalNum;
    }
	
}

4.测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ServerMain.class)
public class RetryTest {
	
	@Autowired
    private RetryService retryService;
	
	
	@Test
    public void test() {
        int count = retryService.retry(-1);
//		int count = retryService.retry(5);
		System.out.println("库存为 :" + count);
	}
	
}

最后提供一个不使用注解的方式,例如动态指定重试次数,等待时间等

// 声明式
	void declarative() {
		final RetryTemplate retryTemplate = new RetryTemplate();
		// 重试次数
        final SimpleRetryPolicy policy = new SimpleRetryPolicy(3, Collections.<Class<? extends Throwable>, Boolean>
                singletonMap(Exception.class, true));
        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        // 重试时间	默认1000ms。
//        fixedBackOffPolicy.setBackOffPeriod(2000);
        retryTemplate.setRetryPolicy(policy);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
        final RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() {
            public Object doWithRetry(RetryContext context) throws Exception {
            	System.out.println("重试次数:"+context.getRetryCount()+", 重试时间:"+LocalTime.now());
            	System.err.println("do some thing");
                //设置context一些属性,给RecoveryCallback传递一些属性
                context.setAttribute("key1", "value1");
                String result = null;
                if (StringUtils.isEmpty(result))
                	throw new Exception("exception");
                return context.getAttribute("key1");
            }
        };

        // 如果RetryCallback执行出现指定异常, 并且超过最大重试次数依旧出现指定异常的话,就执行RecoveryCallback动作
        final RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<Object>() {
            public Object recover(RetryContext context) throws Exception {
                System.err.println("do recory operation");
                System.err.println(context.getAttribute("key1"));
                return null;
            }
        };

        try {
            final Object execute = retryTemplate.execute(retryCallback, recoveryCallback);
            System.err.println(execute);
        } catch (Exception e) {
            e.printStackTrace();
        }
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值