Quartz框架(八)— Quartz实现异步通知

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<当前时间的数据取出,直接调用通知逻辑。

你可能感兴趣的:(Quartz框架(八)— Quartz实现异步通知)