问题 需要在0, 1, 2, 5, 10, 20, 30, 40, 50, 60这样的时间间隔去发送http请求或者做其它事情或者调用三方接口,如果在这个间隔内发送成功,则停止发送
话不多说,先上代码
package com.common.modular.task;
import com.alibaba.fastjson.JSONObject;
import com.common.config.base.BaseTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class SendNoticeTask extends BaseTask {
private static final Logger logger = LoggerFactory.getLogger(SendNoticeTask.class);
public SendNoticeTask() {
logger.info("初始化服务通知定时任务。。。。。。");
}
/**
* 定义一个集合,保存需要发送的定时任务信息,该集合泛型为一个接口
*/
private static final List<INoticeBean> noticeBeanList = new ArrayList<>();
/**
* 添加一个延迟发送任务
* @param noticeBean
*/
public static final void add(NoticeBean noticeBean) {
logger.info("添加服务通知回调{}", noticeBean.name);
noticeBeanList.add(noticeBean);
}
/**
* 启动一个定时任务,每隔60秒执行一次
*/
@Scheduled(cron = "0/60 * * * * ?")
public void task() {
logger.debug("开始发送服务通知。。。。。。");
Iterator<INoticeBean> iterator = noticeBeanList.iterator();
while (iterator.hasNext()) {
INoticeBean noticeBean = iterator.next();
if (noticeBean.sendNotice()) {
iterator.remove();
}
}
}
/**
* 定义需要发送消息的接口
*/
public interface INoticeBean<T> {
/**
* 如果返回true,表名发送成功,则回移除任务,如果返回false,标识发送失败,将在1分钟后再次进行发送
* @return
*/
boolean sendNotice();
}
/**
* 实现该接口,该实现为abstract类,需要具体实现
*/
public abstract static class NoticeBean<T> implements INoticeBean<T> {
private Logger logger = LoggerFactory.getLogger(getClass());
protected boolean isSuccess = false;
protected int sendNum = 0;
private List<Integer> nums;
private int maxLendNum;
private String name;
private T params;
public NoticeBean() {
this(null, UUID.randomUUID().toString());
}
public NoticeBean(String name) {
this(null, name);
}
public NoticeBean(T params, String name) {
this.params = params;
this.name = name;
this.nums = getInterval();
if (this.nums == null) throw new RuntimeException("发送时间间隔数组不能为空");
this.maxLendNum = nums.get(nums.size() - 1);
logger.info("初始化延迟任务:name={}", name);
logger.info("初始化延迟任务:params={}", JSONObject.toJSONString(params));
logger.info("初始化延迟任务:interval={}", JSONObject.toJSONString(nums));
logger.info("初始化延迟任务:maxLendNum={}", maxLendNum);
}
/**
* 获取发送时间间隔
*
* @return
*/
public List<Integer> getInterval() {
return Arrays.asList(0, 1, 2, 5, 10, 20, 30, 40, 50, 60);
}
/**
* 发送服务通知
*/
public boolean sendNotice() {
if (isSuccess) {
logger.info("该任务已经发送成功,不进行发送:{}", name);
return true;
}
boolean isSend = nums.contains(sendNum);
logger.debug("任务[{}],已经持续发送:{},本次是否发送:{}", name, sendNum, isSend);
if (isSend) {
try {
isSuccess = apply(params, sendNum);
if (isSuccess){
success(params, sendNum);
}else{
error(params, sendNum);
}
} catch (Exception e) {
logger.error("本次[{}]发送异常", sendNum, e);
isSuccess = false;
error(params, sendNum);
}
}
sendNum++;
return isRemove();
}
/**
* 判断是否可以移除该任务
*
* @return
*/
protected boolean isRemove() {
if (isSuccess) {
logger.info("发送成功移除任务:{}", name);
return true;
}
boolean isRemove = sendNum > maxLendNum;
if (isRemove) {
logger.info("未发送成功,满足条件移除任务: {}", name);
}
return isRemove;
}
protected abstract boolean apply(T t, int sendNum);
protected void success(T t, int sendNum) {
logger.info("任务[{}]发送成功,sendNum[{}]", name, sendNum);
}
protected void error(T t, int sendNum) {
logger.info("任务[{}]发送失败,sendNum[{}]", name, sendNum);
}
}
}
代码说完了,再说下使用
SendNoticeTask.add(new SendNoticeTask.NoticeBean("测试延迟发送消息定时任务") {
@Override
protected boolean apply(Object params, int sendNum) {
return sendNum > 5;
}
@Override
public List<Integer> getInterval() {
return Arrays.asList(0, 1, 2);
}
});
使用很简单,只需要调用add方法添加一个对象即可,apply方法为必须实现的方法,该方法中实现你需要的业务,构造函数有两个,一个带参数的,一个不带参数的,getInterval为获取时间间隔的方法,因为定时任务是每分钟执行一次,所以这个地方也是按分钟来的,也可以不指定,默认间隔
Arrays.asList(0, 1, 2, 5, 10, 20, 30, 40, 50, 60);
欢迎指点!!!