定时任务调度框架Quartz--集群下的JOB与Trigger操作

文章目录

      • 核心操作
        • 创建一个任务
        • 删除一个任务
        • 修改一个任务
        • 暂停一个任务
        • 恢复一个任务
        • 立即执行任务

SpringBoot下,使用集群配置Quartz链接: 定时任务调度框架Quartz–SpringBoot使用Quartz并使用集群配置

核心操作

创建一个任务

        创建一个任务非常简单,就是根据JOB接口实现类生成一个CronTrigger或者SImpleTrigger,并同时创建一个JobDetail,交给Scheduler调度器即可。具体实现代码完全可以参照CronTrgger与SimpleTrigger

        第一种方案这里需要注意的是,在创建JobDetail的时候,可以增加一个Boolean属性storeDurably,true表明是否该JobDetail在没有任何Trigger与之关联的时候,还存放在数据库中。

    JobDetail jobDetail = newJob(clazz)
                    .withIdentity(param.getName(), param.getGroup())
                    .withDescription(param.getDescription())
                    .usingJobData(new JobDataMap())
                    //没有Trigger与之相关联也会存放在数据库中
                    .storeDurably()
                    .build();
                    
    //入库,方便下一步Trigger与该JobDetail绑定
    scheduler.addJob(jobDetail, false);
    
    //创建CronTrigger,失火策略使用错过不处理
    Trigger cronTrigger = newTrigger()
                    .withIdentity(param.getName(), param.getGroup())
                    .withSchedule(
                           cronSchedule(param.getCron())
                           .withMisfireHandlingInstructionDoNothing()                              
                    )
                    .withDescription(param.getDescription())
                    .forJob(jobDetail)
                    .build();
                    
     scheduler.scheduleJob(cronTrigger);

        第二种方案分别创建CronTriger与JobDetail。然后一次性交给schedule调度器加入调度进程。如果此时在调用一次scheduler.scheduleJob(job,otherTrigger),则会报错。因为Job已经加入到了Schedule调度中,不能重复加入。

    @Autowird
    private SchedulerFactoryBean schedulerFactoryBean;

    public boolean addDynamicScheduleJob(JobParam param) {
     
        try {
     
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(param.getName(), param.getGroup());
            if (scheduler.getTrigger(triggerKey) == null) {
     
                //实现了Job接口的类
                Class clazz = org.apache.commons.lang3.ClassUtils.getClass(param.getClassName());
                if (Job.class.isAssignableFrom(clazz)) {
     
                    //创建CronTrigger,失火策略使用错过不处理
                    Trigger cronTrigger = newTrigger()
                            .withIdentity(param.getName(), param.getGroup())
                            .withSchedule(
                                    cronSchedule(param.getCron())
                                            .withMisfireHandlingInstructionDoNothing()
                            )
                            .withDescription(param.getDescription())
                            .build();

                    //通过Job实现类创建JobDetail
                    JobDetail jobDetail = newJob(clazz)
                            .withIdentity(param.getName(), param.getGroup())
                            .withDescription(param.getDescription())
                            .usingJobData(new JobDataMap())
                            .build();

                    scheduler.scheduleJob(jobDetail, cronTrigger);

                    return Boolean.TRUE;
                } else {
     
                    throw new IllegalArgumentException("class类必须实现Job接口");
                }
            }
        } catch (Exception e) {
     
            LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
        }
        return Boolean.FALSE;
    }
	
	@Data
	public class JobParam {
     
	    private String name;
	    private String cron;
	    private String group;
	    private String className;
	    private String description;
	}

删除一个任务

        其实从作者的注释上来看,如果直接删除Job,那么与之关联的所有Trigger会连带删除。

public interface Scheduler ...
    /**
     * Delete the identified Job from the Scheduler - and any
     * associated Triggers.
     * 
     * @return true if the Job was found and deleted.
     * @throws SchedulerException
     *           if there is an internal Scheduler error.
     */
    boolean deleteJob(JobKey jobKey)
        throws SchedulerException;

        另外一个删除方法是删除Trigger,如果此Trigger关联到的Job没有其他Trigger,那么Job也会被删除。

public interface Scheduler ...
    /**
     * Remove the indicated {@link Trigger} from the scheduler.
     * 
     * 

If the related job does not have any other triggers, and the job is * not durable, then the job will also be deleted.

*/
boolean unscheduleJob(TriggerKey triggerKey) throws SchedulerException;

        一般会按照下方的代码来删除Job与Trigger。先把Trigger暂停。并停止Trigger的调度。最后删除Job。Trigger与Job 一对多,所以先删除Trigger,再删除Job

    public void deleteScheduleByNameAndGroup(String name, String group) {
     
        try {
     
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
            Trigger trigger = scheduler.getTrigger(triggerKey);
            if (trigger == null) {
     
                return;
            }

            JobKey jobKey = JobKey.jobKey(name, group);
            //暂停并不调度触发器
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            //删除任务
            scheduler.deleteJob(jobKey);
        } catch (Exception e) {
     
            LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
            throw new ScheduleRuntimeException(e);
        }
    }

修改一个任务

        修改一个任务很简单,就是通过JobKey删除以前的Trigger。然后再创建一个新的任务

  • 1)通过TriggerKey暂停Trigger调度
  • 2)通过TriggerKey删除Trigger
  • 3)通过JobKey删除JobDetail
  • 4)最后创建新的定时任务,代码参考创建定时任务。创建Trigger与JobDetail交给Scheduler
    @SneakyThrows
    public boolean reloadSchedule(JobParam job) {
     
        //原来的的Job标识
        JobKey jobKey = JobKey.jobKey(job.getSourceName(), job.getSourceGroup()); 
        //新得Job标识
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getSourceName(), job.getSourceGroup());

        //删除原来的Trigger
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        Trigger trigger = scheduler.getTrigger(triggerKey);
        if (trigger != null) {
     
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.deleteJob(jobKey);
        }
        return this.addDynamicScheduleJob(job);
    }

暂停一个任务

        暂停一个定时任务很简单,只需要知道这个任务的name与group即可。从作者的注释来看,让一个JobDetail暂停执行,实际上的实现方式就是让该JobDetail关联的所有Trigger的运行状态改为暂停。

public interface Scheduler ...
    /**
     * Pause the {@link org.quartz.JobDetail} with the given
     * key - by pausing all of its current Triggers.
     * 
     * @see #resumeJob(JobKey)
     */
    void pauseJob(JobKey jobKey)
        throws SchedulerException;

        我把测试的两个Trigger关联了同一个JobDetail,然后调用上述的Scheduler.pauseJob(Jobkey)方法,在QRTZ_TRIGGER表中发现TRIGGER_STATE的状态已经修改为PASUED
定时任务调度框架Quartz--集群下的JOB与Trigger操作_第1张图片

恢复一个任务

        同样得,恢复一个JobDetail也有两种操作:唤醒Trigger与唤醒JobDetail

        下面是通过JobKey恢复任务的源代码。通过JobKey唤醒此JobDetail关联的所有Trigger,并且触发Trigger们的失火策略。

public interface Scheduler ...
    /**
     * Resume (un-pause) the {@link org.quartz.JobDetail} with
     * the given key.
     * 
     * 

* If any of the Job'sTrigger s missed one * or more fire-times, then the Trigger's misfire * instruction will be applied. *

* * @see #pauseJob(JobKey) */
void resumeJob(JobKey jobKey) throws SchedulerException;

        下面是通过TriggerKey恢复任务的源代码。通过TriggerKey唤醒此Trigger,从而让该Trigger开始调度它所关联的JobDetail,同时触发该Trigge的r失火策略。

public interface Scheduler ...
    /**
     * Resume (un-pause) the {@link Trigger} with the given
     * key.
     * 
     * 

* If the Trigger missed one or more fire-times, then the * Trigger's misfire instruction will be applied. *

* * @see #pauseTrigger(TriggerKey) */
void resumeTrigger(TriggerKey triggerKey) throws SchedulerException;

立即执行任务

        立即执行一个任务。从源代码上来看,它创建了一个临时的新的Trigger来安排这次执行任务。不会影响到已经创建并存放在数据库中的Trigger。

public interface Scheduler ...
    /**
     * Trigger the identified {@link org.quartz.JobDetail}
     * (execute it now).
     */
    void triggerJob(JobKey jobKey)
        throws SchedulerException;

你可能感兴趣的:(#,从头开始学Quartz)