zoukankan      html  css  js  c++  java
  • SpringBoot——Quartz定时框架的使用详解和总结

    技术公众号:后端技术解忧铺

    关注微信公众号:CodingTechWork,一起学习进步。

    引言

      一般在使用定时任务时,我们首先会想到使用@Scheduled注解去给某个任务设置定时时间进行定时执行。当定时任务过多时,或者有增删改查需求时,@Scheduled注解将无法满足我们的需求。本文一起学习总结Quartz定时框架的使用。

    Quartz介绍

    概述

    Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.
    Quartz is freely usable, licensed under the Apache 2.0 license.

      Quartz是OpenSymphony开源的一个项目,是一个由Java编写的开源作业调度框架。

    特点

    1. 支持分布式高可用,我们需要某个定时任务在多个节点中只有某个节点可以执行时,就需要Quartz来实现,否则使用@Scheduled等方式会造成所有节点都执行一遍。
    2. 支持持久化,Quartz有专门的数据表来实现定时任务的持久化。
    3. 支持多任务调度和管理,Quartz可以在数据库中存储多个定时任务进行作业调度,可以实现定时任务的增删改查等管理。

    组成

      Quartz由三部分组成:

    1. 任务:JobDetail
    2. 触发器:Trigger(分为SimpleTrigger和CronTrigger)
    3. 调度器:Scheduler

    JobDetail

      JobDetail主要由JobKey(job的名字name和分组group)、JobClass、JobDataMap(任务相关的数据)、JobBuilder组成。常用的是前几个。

    JobDetail源码

    package org.quartz;
    
    import java.io.Serializable;
    
    public interface JobDetail extends Serializable, Cloneable {
        JobKey getKey();
    
        String getDescription();
    
        Class<? extends Job> getJobClass();
    
        JobDataMap getJobDataMap();
    
        boolean isDurable();
    
        boolean isPersistJobDataAfterExecution();
    
        boolean isConcurrentExectionDisallowed();
    
        boolean requestsRecovery();
    
        Object clone();
    
        JobBuilder getJobBuilder();
    }
    


    JobDetail示例

    		Map<String,String> jobData = new HashMap<>();
    		String jobName = "schedulerJob";
    		String jobGroup = "schedulerGroup";
    		jobData.put("key00", "value00");
            JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
                    .withIdentity(jobName, jobGroup)
                    .usingJobData("key01", "value01")
                    .usingJobData(jobData)
                    .storeDurably()
                    .build();
    

    Trigger

      Trigger规定触发执行Job实现类,主要有SimpleTrigger和CronTrigger两个实现类。Trigger由以下部分组成:

    1. TriggerKey(job的名字name和分组group)
    2. JobDataMap(Trigger相关的数据,同JobDetail中JobDataMap,存相同key,若value不同,会覆盖前者。)
    3. ScheduleBuilder(有CronScheduleBuilder、SimpleScheduleBuilder、CalendarIntervalScheduleBuilder、DailyTimeIntervalScheduleBuilder常用前2种。)

      Trigger示例
    	//SimpleScheduleBuilder
    	String triggerName = "schedulerJob";
    	String triggerGroup = "schedulerGroup";
    	Trigger trigger = TriggerBuilder
    	    .newTrigger()
    	    .withIdentity(triggerName, triggerGroup)
    	    .withSchedule(SimpleScheduleBuilder)
    	    .repeatSecondlyForever(1)
    	    .withIntervalInSeconds(0)
    	    .withRepeatCount(0))
    	    .startNow()
    	    .build();
    	
    	//CronScheduleBuilder
    	String triggerName2 = "schedulerJob2";
    	String triggerGroup2 = "schedulerGroup2";
    	String jobTime = "0 0 * * * ?";
    	Trigger trigger2 = TriggerBuilder
    		.newTrigger()
    		.withIdentity(triggerName2, triggerGroup2)
    		.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
    		.withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
    		.startNow()
    		.build();
    

    Scheduler

      调度器就是为了读取触发器Trigger从而触发定时任务JobDetail。可以通过SchedulerFactory进行创建调度器,分为StdSchedulerFactory(常用)和DirectSchedulerFactory两种。

    1. StdSchedulerFactory使用一组属性(放在配置文件中)创建和初始化调度器,然后通过getScheduler()方法生成调度程序。
    2. DirectSchedulerFactory不常用,容易硬编码。

      Scheduler示例
    	//建好jobDetail,trigger
    	... ...
    	//StdSchedulerFactory方式,用的多
    	SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    	Scheduler schedulerStd = schedulerFactory.getScheduler();
    	
    	//DirectSchedulerFactory方式
    	DirectSchedulerFactory directSchedulerFactory = DirectSchedulerFactory.getInstance();
    	Scheduler schedulerDir=directSchedulerFactory.getScheduler();
    	
    	//执行调度
    	schedulerStd.scheduleJob(jobDetail, trigger);
    	schedulerStd.start();
    

    Cron表达式

      定时任务离不开Cron表达式设置具体执行时间或执行周期,Cron表达式是一个字符串,一般有两种表达:

    1. 秒 分 小时 日 月 星期 年
    2. 秒 分 小时 日 月 星期

    其中,年份即为可选的,所以一般表达式为6-7个域,每个域以空格分开。其中的星期除了可以使用英文缩写,也可以用数字1-7数字来表示,注意1表示的是星期日7表示的星期六
    各个域含义

    • *:星号,表示每个字段对应的时间域的每一个,如在日中,就是表示每天。
    • ?:问号,只能在日期和星期字段中使用,表示无意义的值,等价于点位符。
    • -:减号,表示一个范围,如在分钟中使用5-8,则表示5-8分钟,即5、6、7、8分钟。
    • ,:逗号,表示一个列表值,如在星期中星期一和星期三使用MON,WED,也可以使用数字来表示:1,3
    • /:斜杠,使用x/y来表示一个等步长序列,x表示起始值,y表示步长值。如在秒字段中使用0/15,表示从0秒开始,每15秒增量,即0秒,15秒,30秒,45秒,这种就可以理解为每15秒执行任务。
    • L:只能在日期和星期字段中使用,表示Last。在日期中,L表示月份的最后一天,如1月中的31日;在星期中,L表示星期六(或数字7)。
    • W:只能在日期字段中使用,表示离该日期最近的工作期,不可以跨月。如10W,表示离该月10号最近的工作日,若10号为星期六,则匹配9号星期五;若10号为星期日,则匹配11号星期一;若10号为星期一,则匹配10号星期一。LW组合表示该月的最后一个工作日。
    • C:只能在日期和星期字段中使用,表示Calendar,即计划所关联的日期,若日期未被关联,则等价于关联所有日期。如日期中使用4C,表示日期4号以后的第一天;星期中使用1C,表示星期日后的第一天。
    • #:井号只能在星期字段中使用,表示当月某个工作日。如6#2表示当月的第二个星期五(其中,6表示星期五,#3表示当月的第二个).

      Cron示例
    Cron表达式 说明
    0 0 * * * ? 每小时0分0秒运行
    0 0 1 * * ? 每天01:00:00运行运行
    0 0 1 * * ? * 每天01:00:00运行运行,同上
    0 0 1 * * ? 2021 2021年每天01:00:00运行
    0 * 10 * * ? 每天10点-11点之间每分钟运行一次,开始于10:00:00,结束于10:59:00
    0 0/5 10 * * ? 每天10点-11点之间每5分钟运行一次,开始于10:00:00,结束于10:59:00
    0 0/5 10,15 * * ? 每天10点-11点之间每5分钟运行一次,每天15点-16点之间每5分钟运行一次
    0 0-10 10 * * ? 每天10:00-10:10之间每分钟运行
    0 10 1 ? * MON-FRI 每周一,二,三,四,五的1:10分运行
    0 10 1 1 * ? 每月1日的1:10分运行
    0 10 1 L * ? 每月最后一天1:10分运行
    0 10 1 ? * 6L 每月最后一个星期五1:10分运行
    0 10 1 ? * 6#3 每月第3个星期五1:10分运行

    Quartz增删改查模板

    QuartzService接口类

    package com.andya.selfcode.quartzservice;
    
    import org.springframework.scheduling.quartz.QuartzJobBean;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Andya
     * @date 2021/4/01
     */
    public interface QuartzService {
    
        /**
         * 增加一个任务job
         * @param jobClass  任务job实现类
         * @param jobName   任务job名称(保证唯一性)
         * @param jobGroupName  任务job组名
         * @param jobTime   任务时间间隔(秒)
         * @param jobTimes  任务运行次数(若<0,则不限次数)
         * @param jobData   任务参数
         */
        void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                    int jobTimes, Map jobData);
    
        /**
         * 增加一个任务job
         * @param jobClass  任务job实现类
         * @param jobName   任务job名称(保证唯一性)
         * @param jobGroupName  任务job组名
         * @param jobTime   任务时间表达式
         * @param jobData   任务参数
         */
        void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData);
    
        /**
         * 修改一个任务job
         * @param jobName 任务名称
         * @param jobGroupName  任务组名
         * @param jobTime   cron时间表达式
         */
        void updateJob(String jobName, String jobGroupName, String jobTime);
    
        /**
         * 删除一个任务job
         * @param jobName
         * @param jobGroupName
         */
        void deleteJob(String jobName, String jobGroupName);
    
        /**
         * 暂停一个任务job
         * @param jobName
         * @param jobGroupName
         */
        void pauseJob(String jobName, String jobGroupName);
    
        /**
         * 恢复一个任务job
         * @param jobName
         * @param jobGroupName
         */
        void resumeJob(String jobName, String jobGroupName);
    
        /**
         * 立即执行一个任务job
         * @param jobName
         * @param jobGroupName
         */
        void runAJobNow(String jobName, String jobGroupName);
    
        /**
         * 获取所有任务job
         * @return
         */
        List<Map<String, Object>> queryAllJob();
    
        /**
         * 获取正在运行的任务job
         * @return
         */
        List<Map<String, Object>> queryRunJob();
    
    
    }
    
    

    QuartzServiceImpl实现类

    package com.andya.selfcode.quartz.service;
    
    import com.andya.selfcode.quartz.exception.BaseException;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.*;
    import org.quartz.DateBuilder.IntervalUnit;
    import org.quartz.impl.matchers.GroupMatcher;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    import java.util.*;
    
    /**
     * @author Andya
     * @date 2021/4/01
     */
    @Slf4j
    @Service
    public class QuartzServiceImpl implements QuartzService {
    
        @Autowired
        private Scheduler scheduler;
    
        @PostConstruct
        public void startScheduler() {
            try {
                scheduler.start();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 增加一个job
         *
         * @param jobClass
         *            任务实现类
         * @param jobName
         *            任务名称
         * @param jobGroupName
         *            任务组名
         * @param jobTime
         *            时间表达式 (这是每隔多少秒为一次任务)
         * @param jobTimes
         *            运行的次数 (<0:表示不限次数)
         * @param jobData
         *            参数
         */
        @Override
        public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                           int jobTimes, Map jobData) {
            try {
                // 任务名称和组构成任务key
                JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                        .build();
                // 设置job参数
                if(jobData!= null && jobData.size()>0){
                    jobDetail.getJobDataMap().putAll(jobData);
                }
                // 使用simpleTrigger规则
                Trigger trigger = null;
                if (jobTimes < 0) {
                    trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                            .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
                            .startNow().build();
                } else {
                    trigger = TriggerBuilder
                            .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
                                    .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
                            .startNow().build();
                }
                log.info("jobDataMap: {}", jobDetail.getJobDataMap().getWrappedMap());
                scheduler.scheduleJob(jobDetail, trigger);
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("add job error!");
            }
        }
    
        /**
         * 增加一个job
         *
         * @param jobClass
         *            任务实现类
         * @param jobName
         *            任务名称(建议唯一)
         * @param jobGroupName
         *            任务组名
         * @param jobTime
         *            时间表达式 (如:0/5 * * * * ? )
         * @param jobData
         *            参数
         */
        @Override
        public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData) {
            try {
                // 创建jobDetail实例,绑定Job实现类
                // 指明job的名称,所在组的名称,以及绑定job类
                // 任务名称和组构成任务key
                JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                        .build();
                // 设置job参数
                if(jobData!= null && jobData.size()>0){
                    jobDetail.getJobDataMap().putAll(jobData);
                }
                // 定义调度触发规则
                // 使用cornTrigger规则
                // 触发器key
                Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                        .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();
                // 把作业和触发器注册到任务调度中
                scheduler.scheduleJob(jobDetail, trigger);
                log.info("jobDataMap: {}", jobDetail.getJobDataMap());
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseException("add job error!");
            }
        }
    
        /**
         * 修改 一个job的 时间表达式
         *
         * @param jobName
         * @param jobGroupName
         * @param jobTime
         */
        @Override
        public void updateJob(String jobName, String jobGroupName, String jobTime) {
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                log.info("new jobTime: {}", jobTime);
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
                // 重启触发器
                scheduler.rescheduleJob(triggerKey, trigger);
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("update job error!");
            }
        }
    
        /**
         * 删除任务一个job
         *
         * @param jobName
         *            任务名称
         * @param jobGroupName
         *            任务组名
         */
        @Override
        public void deleteJob(String jobName, String jobGroupName) {
            try {
                scheduler.deleteJob(new JobKey(jobName, jobGroupName));
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseException("delete job error!");
            }
        }
    
        /**
         * 暂停一个job
         *
         * @param jobName
         * @param jobGroupName
         */
        @Override
        public void pauseJob(String jobName, String jobGroupName) {
            try {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
                scheduler.pauseJob(jobKey);
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("pause job error!");
            }
        }
    
        /**
         * 恢复一个job
         *
         * @param jobName
         * @param jobGroupName
         */
        @Override
        public void resumeJob(String jobName, String jobGroupName) {
            try {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
                scheduler.resumeJob(jobKey);
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("resume job error!");
            }
        }
    
        /**
         * 立即执行一个job
         *
         * @param jobName
         * @param jobGroupName
         */
        @Override
        public void runAJobNow(String jobName, String jobGroupName) {
            try {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
                scheduler.triggerJob(jobKey);
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("run a job error!");
            }
        }
    
        /**
         * 获取所有计划中的任务列表
         *
         * @return
         */
        @Override
        public List<Map<String, Object>> queryAllJob() {
            List<Map<String, Object>> jobList = null;
            try {
                GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
                Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
                jobList = new ArrayList<Map<String, Object>>();
                for (JobKey jobKey : jobKeys) {
                    log.info("maps: {}", scheduler.getJobDetail(jobKey).getJobDataMap().getWrappedMap());
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    for (Trigger trigger : triggers) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("jobName", jobKey.getName());
                        map.put("jobGroupName", jobKey.getGroup());
                        map.put("description", "触发器:" + trigger.getKey());
                        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                        map.put("jobStatus", triggerState.name());
                        if (trigger instanceof CronTrigger) {
                            CronTrigger cronTrigger = (CronTrigger) trigger;
                            String cronExpression = cronTrigger.getCronExpression();
                            map.put("jobTime", cronExpression);
                        }
                        jobList.add(map);
                    }
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("query all jobs error!");
            }
            return jobList;
        }
    
        /**
         * 获取所有正在运行的job
         *
         * @return
         */
        @Override
        public List<Map<String, Object>> queryRunJob() {
            List<Map<String, Object>> jobList = null;
            try {
                List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
                jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
                for (JobExecutionContext executingJob : executingJobs) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    JobDetail jobDetail = executingJob.getJobDetail();
                    JobKey jobKey = jobDetail.getKey();
                    Trigger trigger = executingJob.getTrigger();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description", "触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression);
                    }
                    jobList.add(map);
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
                throw new BaseException("query run jobs error!");
            }
            return jobList;
        }
    
    }
    
    

    Quartz使用方式

    应用启动时自动调用

      写一个配置类,使用@Bean注解进行配置实例化。

    QuartzConfig配置类

    package com.andya.selfcode.quartz;
    
    import org.quartz.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Service;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    @Configuration
    @Service
    public class QuartzConfig {
    
        @Bean
        public JobDetail scheduleJobDetail() {
            System.out.println("**************************************** scheduler job begin");
            JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
                    .withIdentity("schedulerJob")
                    .storeDurably()
                    .build();
            System.out.println("**************************************** scheduler job end");
            return jobDetail;
        }
    
        @Bean
        public Trigger scheduleJobDetailTrigger() {
            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .forJob(scheduleJobDetail())
                    .withIdentity("schedulerJob")
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
                    .startNow()
                    .build();
            System.out.println("schedulerJob trigger end");
            return trigger;
        }
    

    SchedulerJob任务类增删

    package com.andya.selfcode.quartz;
    
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    @Slf4j
    public class SchedulerJob extends QuartzJobBean {
    
        @Autowired
        QuartzService quartzService;
    
        @Value("${schedule.cron.withJob1}")
        private String cronTimeJob1;
    
        public String getCronTimeJob1() {
            return cronTimeJob1;
        }
    
        @Value("${schedule.cron.withJob2}")
        private String cronTimeJob2;
    
        public String getCronTimeJob1() {
            return cronTimeJob2;
        }
    
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            try{
                //job1先删后增
                log.info("job1: delete scheduleWithJob1");
                quartzService.deleteJob("scheduleWithJob1", "scheduleWithJob1_Group1");
    
                log.info("job1: add scheduleWithJob1");
                quartzService.addJob(ScheduleWithJob1.class, "scheduleWithJob1",
                        "scheduleWithJob1_Group1", cronTimeJob1, null);
    
                //按小时定时的job先删后增
                log.info("job2: delete scheduleWithJob2");
                quartzService.deleteJob("scheduleWithJob2", "scheduleWithJob2_Group2");
    
                log.info("job2: add scheduleWithJob2");
                quartzService.addJob(ScheduleWithJob2.class, "scheduleWithJob2",
                        "scheduleWithJob2_Group2", cronTimeJob2, null);
            } catch (Exception e) {
                log.error("quartz service scheduler job failed!");
                e.printStackTrace();
            }
        }
    }
    
    

    具体Job任务类

    ScheduleWithJob1类

    package com.andya.selfcode.quartz;
    
    import com.andya.selfcode.service.ScheduleJobService;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    import java.time.LocalDateTime;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    @Slf4j
    public class ScheduleWithJob1 extends QuartzJobBean {
    
        @Autowired
        ScheduleJobService scheduleJobService;
    
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException{
            System.out.println("start schedule job1: " + LocalDateTime.now());
            try {
                scheduleJobService.scheduleWithJob1();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    

    ScheduleWithJob2类

    package com.andya.selfcode.quartz;
    
    import com.andya.selfcode.service.ScheduleJobService;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    import java.time.LocalDateTime;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    public class ScheduleWithJob2 extends QuartzJobBean {
    
        @Autowired
        ScheduleJobService scheduleJobService;
    
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            try {
                System.out.println("start schedule with job2: " + LocalDateTime.now());
                scheduleJobService.scheduleJob2();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    ScheduleJobService接口类

    package com.andya.selfcode.service;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    public interface ScheduleJobService {
    
        /**
         * job1定时任务
         * @throws Exception
         */
        void scheduleJob1() throws Exception;
    
        /**
         * job2定时任务
         * @throws Exception
         */
        void scheduleJob2() throws Exception;
    }
    
    

    HTTP接口方式调用

      写一个controller层直接调用QuartzService接口类。

    package com.andya.selfcode.quartz.controller;
    
    import com.andya.selfcode.quartz.bean.UpdateJobBean;
    import com.andya.selfcode.quartz.bean.JobXXXBean;
    import com.andya.selfcode.quartz.exception.BadRequestException;
    import com.andya.selfcode.quartz.service.QuartzService;
    import com.andya.selfcode.quartz.service.jobs.Job1;
    import io.swagger.annotations.*;
    import org.quartz.JobDataMap;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    @RestController
    @Api(value = "quartz增删改查相关API")
    @RequestMapping(value = "/quartz")
    public class YarnFlexibleCapacityExpansionController {
    
        @Autowired
        QuartzService quartzService;
    
        @ApiOperation(value = "使用quartz添加job")
        @RequestMapping(value = "/addJob/{jobUUID}", method = RequestMethod.POST)
        public void addQuartzJob(
                @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
                @ApiParam(name = "JobXXXBean") @RequestBody JobXXXBean jobXXXBean) {
    
            if (jobXXXBean.getOpenBean() != null) {
                JobDataMap jobDataMap = new JobDataMap();
                jobDataMap.put("key01", jobXXXBean.getKey01());
                jobDataMap.put("key02", jobXXXBean.getKey02());
                jobDataMap.put("key03", jobXXXBean.getKey03());
                jobDataMap.put("jobTimeCron", jobXXXBean.getJobTimeCron());
                jobDataMap.put("key04", jobXXXBean.getKey04());
                quartzService.addJob(Job1.class,
                        jobUUID,
                        jobUUID,
                        jobXXXBean.getJobTimeCron(),
                        jobDataMap);
            } else {
                throw new BadRequestException("参数错误");
            }
        }
    
    
        @ApiOperation(value = "使用quartz查询所有job")
        @RequestMapping(value = "/queryAllJob", method = RequestMethod.GET)
        public List<Map<String, Object>> queryAllQuartzJob() {
    
            List<Map<String, Object>> list = quartzService.queryAllJob();
            return list;
        }
    
    
        @ApiOperation(value = "使用quartz查询所有运行job")
        @RequestMapping(value = "/queryRunJob", method = RequestMethod.GET)
        public List<Map<String, Object>> queryRunQuartzJob() {
    
            List<Map<String, Object>> list = quartzService.queryRunJob();
            return list;
        }
    
        @ApiOperation(value = "使用quartz删除job")
        @RequestMapping(value = "/deleteJob/{jobUUID}", method = RequestMethod.DELETE)
        public void deleteJob(
                @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID) {
    
            quartzService.deleteJob(jobUUID, jobUUID);
        }
    
    
        @ApiOperation(value = "使用quartz修改job的cron时间")
        @RequestMapping(value = "/updateJob/{jobUUID}", method = RequestMethod.PUT)
        public void deleteJob(
                @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
                @ApiParam(name = "jobCronTime") @RequestBody UpdateJobBean updateJobBean) {
    
            quartzService.updateJob(jobUUID, jobUUID, updateJobBean.getJobCronTime());
    
        }
    }
    
    
    /**
     * @author Andya
     * @create 2021/04/01
     */
    @ApiModel(value = "更新job cron时间参数")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class UpdateJobBean {
        @ApiModelProperty(value = "jobTime的cron表达式", example = "0 0 1 * * ?")
        String jobCronTime;
    
        public String getJobCronTime() {
            return jobCronTime;
        }
    
        public void setJobCronTime(String jobCronTime) {
            this.jobCronTime = jobCronTime;
        }
    }
    

    Quartz数据表脚本

    quartz初始化数据表的sql脚本如下。

    -- 1.1. qrtz_blob_triggers : 以Blob 类型存储的触发器。
    -- 1.2. qrtz_calendars:存放日历信息, quartz可配置一个日历来指定一个时间范围。
    -- 1.3. qrtz_cron_triggers:存放cron类型的触发器。
    -- 1.4. qrtz_fired_triggers:存放已触发的触发器。
    -- 1.5. qrtz_job_details:存放一个jobDetail信息。
    -- 1.6. qrtz_job_listeners:job监听器。
    -- 1.7. qrtz_locks: 存储程序的悲观锁的信息(假如使用了悲观锁)。
    -- 1.8. qrtz_paused_trigger_graps:存放暂停掉的触发器。
    -- 1.9. qrtz_scheduler_state:调度器状态。
    -- 1.10. qrtz_simple_triggers:简单触发器的信息。
    -- 1.11. qrtz_trigger_listeners:触发器监听器。
    -- 1.12. qrtz_triggers:触发器的基本信息。
    
    DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
    DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
    DROP TABLE IF EXISTS QRTZ_LOCKS;
    DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
    DROP TABLE IF EXISTS QRTZ_CALENDARS;
    
    CREATE TABLE QRTZ_JOB_DETAILS(
    SCHED_NAME VARCHAR(120) NOT NULL,
    JOB_NAME VARCHAR(190) NOT NULL,
    JOB_GROUP VARCHAR(190) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    JOB_CLASS_NAME VARCHAR(250) NOT NULL,
    IS_DURABLE VARCHAR(1) NOT NULL,
    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    JOB_NAME VARCHAR(190) NOT NULL,
    JOB_GROUP VARCHAR(190) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    NEXT_FIRE_TIME BIGINT(13) NULL,
    PREV_FIRE_TIME BIGINT(13) NULL,
    PRIORITY INTEGER NULL,
    TRIGGER_STATE VARCHAR(16) NOT NULL,
    TRIGGER_TYPE VARCHAR(8) NOT NULL,
    START_TIME BIGINT(13) NOT NULL,
    END_TIME BIGINT(13) NULL,
    CALENDAR_NAME VARCHAR(190) NULL,
    MISFIRE_INSTR SMALLINT(2) NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
    REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    REPEAT_COUNT BIGINT(7) NOT NULL,
    REPEAT_INTERVAL BIGINT(12) NOT NULL,
    TIMES_TRIGGERED BIGINT(10) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_CRON_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    CRON_EXPRESSION VARCHAR(120) NOT NULL,
    TIME_ZONE_ID VARCHAR(80),
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_SIMPROP_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(190) NOT NULL,
        TRIGGER_GROUP VARCHAR(190) NOT NULL,
        STR_PROP_1 VARCHAR(512) NULL,
        STR_PROP_2 VARCHAR(512) NULL,
        STR_PROP_3 VARCHAR(512) NULL,
        INT_PROP_1 INT NULL,
        INT_PROP_2 INT NULL,
        LONG_PROP_1 BIGINT NULL,
        LONG_PROP_2 BIGINT NULL,
        DEC_PROP_1 NUMERIC(13,4) NULL,
        DEC_PROP_2 NUMERIC(13,4) NULL,
        BOOL_PROP_1 VARCHAR(1) NULL,
        BOOL_PROP_2 VARCHAR(1) NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_BLOB_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    BLOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_CALENDARS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    CALENDAR_NAME VARCHAR(190) NOT NULL,
    CALENDAR BLOB NOT NULL,
    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_FIRED_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    ENTRY_ID VARCHAR(95) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) NOT NULL,
    INSTANCE_NAME VARCHAR(190) NOT NULL,
    FIRED_TIME BIGINT(13) NOT NULL,
    SCHED_TIME BIGINT(13) NOT NULL,
    PRIORITY INTEGER NOT NULL,
    STATE VARCHAR(16) NOT NULL,
    JOB_NAME VARCHAR(190) NULL,
    JOB_GROUP VARCHAR(190) NULL,
    IS_NONCONCURRENT VARCHAR(1) NULL,
    REQUESTS_RECOVERY VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,ENTRY_ID))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_SCHEDULER_STATE (
    SCHED_NAME VARCHAR(120) NOT NULL,
    INSTANCE_NAME VARCHAR(190) NOT NULL,
    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_LOCKS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME VARCHAR(40) NOT NULL,
    PRIMARY KEY (SCHED_NAME,LOCK_NAME))
    ENGINE=InnoDB;
    
    CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
    CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
    
    CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
    CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
    CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
    
    CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
    CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
    CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
    CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
    
    commit;
    

    refer by
    http://www.quartz-scheduler.org/

    烧不死的鸟就是凤凰
  • 相关阅读:
    IOS开发之----设置UITableView背景色和选中背景色
    IOS开发之 ---- iOS8中提示框的使用UIAlertController(UIAlertView和UIActionSheet二合一)
    iOS如何将你的程序打包成ipa
    苹果企业开发者账号申请记录
    UIButton上图片和文字的位置调整
    试图添加进 ScrollerVier 的视图里,默认下移64个像素
    NetworkManger解析 xcode7.0以上要改字段
    iOS 登录功能的实现
    keyboard和 UITextFiled 之间的处理
    curator zookeeper监控。SpiderWatcher
  • 原文地址:https://www.cnblogs.com/Andya/p/14609065.html
Copyright © 2011-2022 走看看