springboot整合quartz(二)

https://blog.csdn.net/java_chegnxuyuan/article/details/90205205

在上一篇中我介绍了springboot与quartz的简单的实现以及Job和JobDetail的部分内容。这篇继续介绍Triggers的使用

Triggers具体可以分为SimpleTrigger和CronTrigger。

1.SimpleTrigger:

可以满足的调度需求是,在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。比如,你有一个trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或者在这个时间点触发,并且每隔2秒触发一次,一共重复5次。

根据描述,你可能已经发现了,SimpleTrigger的属性包括:开始时间、结束时间、重复次数以及重复的间隔。这些属性的含义与你所期望的是一致的,只是关于结束时间有一些地方需要注意。

在上一篇的继续上修改代码如下:会发现第一次执行的时间为2019-05-14 16:07:07,最后一次执行时间为2019-05-14 16:07:57

springboot整合quartz(二)

endTime属性的值会覆盖设置重复次数的属性值;比如,你可以创建一个trigger,在终止时间之前每隔10秒执行一次,你不需要去计算在开始时间和终止时间之间的重复次数,只需要设置终止时间并将重复次数设置为REPEAT_INDEFINITELY(当然,你也可以将重复次数设置为一个很大的值,并保证该值比trigger在终止时间之前实际触发的次数要大即可)。

2.CronTrigger

CronTrigger通常比Simple Trigger更有用,如果您需要基于日历的概念而不是按照SimpleTrigger的精确指定间隔进行重新启动的作业启动计划。

使用CronTrigger,您可以指定号时间表,例如“每周五中午”或“每个工作日和上午9:30”,甚至“每周一至周五上午9:00至10点之间每5分钟”和1月份的星期五“。

即使如此,和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止计划。

关于corn表达式,可以直接从http://cron.qqe2.com/网站上生产

修改代码如下:

public class TestQuartz {

    public static void main(String[] args) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        /**
         * 表示一个具体的可执行的调度程序
         */
        JobDetail jobDetail = newJob(JobQuartz.class).withIdentity("myJob", "group1")
                .usingJobData("jobSays", "Hello World!")
                .usingJobData("myFloatValue", 3.141f)
                .build();
        //定义一个Trigger
        /*Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                           .startNow()
                            //每个5秒钟执行一次
                            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5)
                                 //重复执行
                                .withRepeatCount(5)
                            ).build();*/

        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                          .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))//每10秒执行一次
                          .build();


        //创建scheduler
        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.scheduleJob(jobDetail, cronTrigger);
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

quartz中的TriggerListeners和JobListeners

1.JobListeners

创建JobQuartzListener类,并实现JobListener接口

public class JobQuartzListener implements JobListener {

    /**
     * 相当于为我们的监听器命名
     * @return
     */
    @Override
    public String getName() {
        return "myJobListener";
    }

    /**
     * (1)
     * 任务执行之前执行
     * @param jobExecutionContext
     */
    @Override
    public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
        System.out.println("MyJobListener.jobToBeExecuted()");
    }

    /**
     * (2)
     * 这个方法正常情况下不执行,但是如果当TriggerListener中的vetoJobExecution方法返回true时,那么执行这个方法
     *  需要注意的是 如果方法(2)执行 那么(1),(3)这个俩个方法不会执行,因为任务被终止了嘛.
     */
    @Override
    public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
        System.out.println("MyJobListener.jobExecutionVetoed()");
    }

    /**
     * (3)
     *  任务执行完成后执行,jobException如果它不为空则说明任务在执行过程中出现了异常
     * @param jobExecutionContext
     * @param e
     */
    @Override
    public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
        System.out.println("MyJobListener.jobWasExecuted()");
    }
}

在scheduler中将自己创建的JobQuartzListener注入进去

需要注意的是,scheduler注入的时候有多种注入方式

1.全局注册,所有Job都会起作用

scheduler.getListenerManager().addJobListener(new JobQuartzListener());

2.指定具体的任务

Matcher<JobKey> matcher = KeyMatcher.keyEquals(new JobKey("job1", "group1"));
sched.getListenerManager().addJobListener(new MyJobListener(), matcher);

3.指定一组任务

GroupMatcher<JobKey> matcher = GroupMatcher.jobGroupEquals("group1");
sched.getListenerManager().addJobListener(new MyJobListener(), matcher);

4.可以根据组的名字匹配开头和结尾或包含

GroupMatcher<JobKey> matcher = GroupMatcher.groupStartsWith("g");
GroupMatcher<JobKey> matcher = GroupMatcher.groupContains("g");
sched.getListenerManager().addJobListener(new MyJobListener(), matcher);

我们这里测试时使用的是第一种方式

springboot整合quartz(二)

2.TriggerListener 

创建TriggerQuartzListener类,并实现TriggerListener接口

public class TriggerQuartzListener implements TriggerListener {
    @Override
    public String getName() {
        return "myTriggerListener";
    }

    /**
     * (1)
     * Trigger被激发 它关联的job即将被运行
     */
    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) {
        System.out.println(" Trigger 被触发了,此时Job 上的 execute() 方法将要被执行");
    }

    /**
     * (2)
     * Trigger被激发 它关联的job即将被运行,先执行(1),在执行(2) 如果返回TRUE 那么任务job会被终止
     */
    @Override
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) {
        System.out.println("发现此次Job的相关资源准备存在问题,不便展开任务,返回true表示否决此次任务执行");
        return false;//如果这里为true,则任务不会执行
    }

    /**
     * (3) 当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行,但是线程池中的有效线程都在工作,
     *  那么有的触发器就有可能超时,错过这一轮的触发。
     */
    @Override
    public void triggerMisfired(Trigger trigger) {
        System.out.println( "当前Trigger触发错过了");
    }

    /**
     * (4) 任务完成时触发
     */
    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) {
        System.out.println("Trigger 被触发并且完成了 Job 的执行,此方法被调用");
    }
}

在scheduler中注入TriggerQuartzListener时和job的注入一致。