Quartz框架(八)— Quartz实现异步通知
2019-07-09 本文已影响0人
小胖学编程
Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore数据库表字段详解
Quartz框架(三)—任务的并行/串行执行
Quartz框架(四)—misfire处理机制
Quartz框架(五)— 有状态的job和无状态job
Quartz框架(六)— Trigger状态转换
Quartz框架(七)— Quartz集群原理
Quartz框架(八)— Quartz实现异步通知
Quartz框架(九)— 动态操作Quartz定时任务
Quartz框架(十)监听
使用Quartz如何实现梯度的异步通知呢?
1. 一个Job绑定多个触发器
一个Trigger只能绑定一个Job,但是一个Job可以绑定多个Trigger。
那么,若是我们将一个Job上绑定多个触发器,且每个触发器只是触发一次的话,那么,实际上我们便可以实现阶梯式的异步通知。
程序代码
public class TestQuartzForMoreJob {
Logger logger=LoggerFactory.getLogger(TestQuartzForMoreJob.class);
@Test
public void test() {
SimpleScheduleBuilder scheduleBuilder1=SimpleScheduleBuilder.repeatSecondlyForTotalCount(1);
//任务
JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
.withIdentity("job1", "job_group1")
.storeDurably()
.build();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date();
Date date1 = addSecond(date, 5);
Date date2 = addSecond(date, 15);
//日志打印
logger.info("获取到任务的时间:"+sdf.format(date));
logger.info("第一次通知的时间:"+sdf.format(date1));
logger.info("第二次通知的时间:"+sdf.format(date2));
//触发器1
SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1")
.withSchedule(scheduleBuilder1)
.startAt(date1)
.forJob(new JobKey("job1", "job_group1"))
.build();
//触发器2
SimpleTrigger trigger2 = newTrigger().withIdentity("trigger2", "group1")
.withSchedule(scheduleBuilder1)
.forJob(new JobKey("job1", "job_group1"))
.startAt(date2)
.build();
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//多触发器关联
scheduler.scheduleJob(jobDetail, trigger);
scheduler.scheduleJob(trigger2);
scheduler.start();
Thread.sleep(100000);
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static Date addSecond(Date date, int second) {
java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.setTime(date);
// calendar.add(Calendar.MINUTE, minute);
calendar.add(Calendar.SECOND, second);
return calendar.getTime();
}
}
日志打印
17:19:53.215 [main] INFO com.com.tellme.TestQuartzForMoreJob - 获取到任务的时间:2019-07-09 05:19:53
17:19:53.220 [main] INFO com.com.tellme.TestQuartzForMoreJob - 第一次通知的时间:2019-07-09 05:19:58
17:19:53.220 [main] INFO com.com.tellme.TestQuartzForMoreJob - 第二次通知的时间:2019-07-09 05:20:08
17:19:58.218 [DefaultQuartzScheduler_Worker-1] INFO com.com.tellme.HelloQuartz - 多触发器测试,时间:2019-07-09 05:19:58
17:20:08.211 [DefaultQuartzScheduler_Worker-2] INFO com.com.tellme.HelloQuartz - 多触发器测试,时间:2019-07-09 05:20:08
2. 定时轮询数据库
这个思想是将需要异步通知的数据保存到数据表中,该表的结构有这么几个主要的字段:
CREATE TABLE `yy_notify` (
`TXN_ID` varchar(32) NOT NULL COMMENT '系统单号',
`SERVICE_ID` varchar(255) NOT NULL COMMENT 'Spring Bean id',
`SCAN_STATUS` varchar(2) DEFAULT NULL COMMENT '扫描状态(00:待扫描,01:不扫描)',
`SCAN_TIMES` int(1) DEFAULT '0' COMMENT '扫描次数',
`NEXT_SCAN_TIME` timestamp NULL DEFAULT NULL COMMENT '下次扫描时间,用于梯度查询场景',
`NOTIFY_STATUS` varchar(255) DEFAULT NULL COMMENT '(02-通知成功,03-通知返回失败,01-未通知)',
`CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`MODIFY_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`TXN_ID`) USING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
每1分钟轮询一次该表,将该表中NOTIFY_STATUS=未通知,SCAN_TIMES<=最大扫描次数,NEXT_SCAN_TIME<当前时间的数据取出,直接调用通知逻辑。