Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore數據庫表字段詳解
Quartz框架(三)—任務的並行/串行執行
Quartz框架(四)—misfire處理機制
Quartz框架(五)— 有狀態的job和無狀態job
Quartz框架(六)— Trigger狀態轉換
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<當前時間的數據取出,直接調用通知邏輯。