1,添加maven依赖
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
2,定义重试机制
Retryer<CMSResultDTO> smsRetryer = RetryerBuilder.<CMSResultDTO>newBuilder()
.retryIfResult(cmsResultDTO->cmsResultDTO.getCode() != SM_SUCCESS_CODE) // 短信返回的码不是200要重试
.retryIfResult(Predicates.<CMSResultDTO>isNull()) // 返回的数据是null要重试
.retryIfExceptionOfType(Exception.class) // 返回的异常错误类
.withStopStrategy(StopStrategies.stopAfterAttempt(ATTEMPT_NUM))
.withWaitStrategy(WaitStrategies.fixedWait(SLEEP_TIME, TimeUnit.SECONDS)) // 隔1秒重试
.withRetryListener(new SMRetryListener<>())
.build();
3,定义要重试的任务
Callable<CMSResultDTO> task = ()->{
log.info("sm input param:type=>{}, interCode=>{}, mobile=>{}, pair=>{}",
type, interCode, mobile, pair);
CMSResultDTO cmsResultDTO = cmsService.sendMessage(type, interCode, mobile, pair);
log.info("sm return data:{}", JSON.toJSONString(cmsResultDTO));
return cmsResultDTO;
};
4,重试机制重试任务
CMSResultDTO cmsResultDTO = null;
try {
cmsResultDTO = smsRetryer.call(task);
} catch (ExecutionException e) {
log.error("SM ExecutionException", e);
} catch (RetryException e) {
log.error("SM RetryException", e);
}
return cmsResultDTO;
以下是一个关于重试发短信的完整例子
/**
* 重试机制 发送短信接口支持国际码
* @param type 模版号
* @param interCode 国际码
* @param mobile 手机号码
* @param pair 参数对
* @return 消息发送结果,包括发送状态和消息标识
*/
public CMSResultDTO retrySendMessage(Integer type, String interCode, String mobile, Map<String, String> pair) throws CMSQueueException, CMSSendException {
Preconditions.checkNotNull(type, "type不能为null");
Preconditions.checkNotNull(interCode, "interCode不能为null");
Preconditions.checkNotNull(mobile, "mobile不能为null");
Preconditions.checkNotNull(pair, "pair不能为null");
Callable<CMSResultDTO> task = ()->{
log.info("sm input param:type=>{}, interCode=>{}, mobile=>{}, pair=>{}",
type, interCode, mobile, pair);
//调用第三方发短信接口,得到返回值,第一时间记录到log中
CMSResultDTO cmsResultDTO = cmsService.sendMessage(type, interCode, mobile, pair);
log.info("sm return data:{}", JSON.toJSONString(cmsResultDTO));
return cmsResultDTO;
};
//定义重试的机制原理
Retryer<CMSResultDTO> smsRetryer = RetryerBuilder.<CMSResultDTO>newBuilder()
.retryIfResult(cmsResultDTO->cmsResultDTO.getCode() != SM_SUCCESS_CODE) // 短信返回的码不是200要重试
.retryIfResult(Predicates.<CMSResultDTO>isNull()) // 返回的数据是null要重试
.retryIfExceptionOfType(Exception.class) // 返回的异常错误类
.withStopStrategy(StopStrategies.stopAfterAttempt(ATTEMPT_NUM))
.withWaitStrategy(WaitStrategies.fixedWait(SLEEP_TIME, TimeUnit.SECONDS)) // 隔1秒重试
//监听器
.withRetryListener(new SMRetryListener<>())
.build();
CMSResultDTO cmsResultDTO = null;
try {
//执行任务的重试,得到返回结果
cmsResultDTO = smsRetryer.call(task);
} catch (ExecutionException e) {
log.error("SM ExecutionException", e);
} catch (RetryException e) {
log.error("SM RetryException", e);
}
return cmsResultDTO;
}
//自定义的监听器
/**
* 重试监听器
* @param <CMSResultDTO>
*/
private class SMRetryListener<CMSResultDTO> implements RetryListener {
@Override
public <CMSResultDTO> void onRetry(Attempt<CMSResultDTO> attempt) {
log.info("[retry]time=" + attempt.getAttemptNumber());
if (attempt.hasException()) {
log.error("retry exception", attempt.getExceptionCause());
}
if (attempt.hasResult()) {
if (attempt.getResult() == null) {
log.info("retry return data is null");
} else {
log.info("retry return data is:{}", JSON.toJSONString(attempt.getResult()));
}
}
}
}