springbootz整合quartz

近期公司项目任务,需要在项目中添加定时任务,整理了一天,在项目中已经可用

quartz概述

Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。主要用来执行定时任务

quartz核心元素

Quartz核心要素有Scheduler、Trigger、Job、JobDetail,其中trigger和job、jobDetail为元数据,而Scheduler为实际进行调度的控制器。

以上都是摘抄于百度,现在来写一下步骤

整合quartz

  • 前期准备工作
    pom.xml
		<dependency> <!--quartz依赖-->
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
 

quartz需要的表

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;
-- 存储每一个已配置的Job的详细信息
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) 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;
-- 存储已配置的Trigger的信息
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) 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(200) 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;
-- 存储已配置的Simple Trigger的信息
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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;
-- 存储Cron Trigger,包括Cron表达式和时区信息
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(200) NOT NULL,
   TRIGGER_GROUP VARCHAR(200) 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;
--  Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore并不知道如何存储实例的时候)
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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;
-- 以Blob类型存储Quartz的Calendar日历信息,quartz可配置一个日历来指定一个时间范围
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
-- 存储已暂停的Trigger组的信息
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
-- 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) 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(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
-- 存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) 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;
  • 任务实体类,这个类是自己定义的实体类,可以根据自己的项目需求来定
public class Job implements Serializable {

    /**
	 * 
	 */
	private static final long serialVersionUID = -8753803549325852334L;

	private Integer jobId;

	private String jobName;
	
    private String params; //参数
    
    private Date runTime;
    
    private String cronExpression; //cron表达式

    private Byte status; //任务状态 0,运行 1,暂停

    private String remark; //备注
  • 配置类
@Configuration
public class QuartzConfig {
   
   @Autowired
   DataSource dataSource;
   
   @Bean
   public SchedulerFactoryBean scheduler() {

       //quartz参数
       Properties prop = new Properties();
       //配置实例
       prop.put("org.quartz.scheduler.instanceId", "AUTO");
       //线程池配置
       prop.put("org.quartz.threadPool.threadCount", "5");
       //JobStore配置
       prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
       prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");

       SchedulerFactoryBean factory = new SchedulerFactoryBean();
       factory.setDataSource(dataSource);
       factory.setQuartzProperties(prop);
       factory.setSchedulerName("MyScheduler");//数据库中存储的名字
       //QuartzScheduler 延时启动,应用启动5秒后 QuartzScheduler 再启动
       factory.setStartupDelay(5);

       //factory.setApplicationContextSchedulerContextKey("applicationContextKey");
       //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
       factory.setOverwriteExistingJobs(true);
       //设置自动启动,默认为true
       factory.setAutoStartup(true);

       return factory;
   }
}
  • 定时器方法(类似于工具类,启动,暂停都在此类中)
public class SchedulerUtils {

   /**
    * 创建任务
    */
   public static void createJob(Scheduler scheduler, Job scheduleJob) {

       try {
           Integer jobId = scheduleJob.getJobId();
           //创建Job对象
           JobDetail job = JobBuilder.newJob(QuartzJob.class).withIdentity("JOB_" + jobId).build();
           //获取cron表达式 并创建对象
           CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                   .withMisfireHandlingInstructionDoNothing();
           //创建触发器
           CronTrigger trigger = TriggerBuilder.newTrigger()
                   .withIdentity("TRIGGET_" + jobId)
                   .withSchedule(cronScheduleBuilder) //将cron表达式配置到触发器
                   .build();

           //将对象josn序列化存储到Job的getJobDataMap()方法中,为后续根据获取属性执行对应的类的任务
           job.getJobDataMap().put("JOB_PARAM_KEY", JSON.toJSONString(scheduleJob));
           //存数据
           scheduler.scheduleJob(job, trigger);
          // scheduler.pauseJob(JobKey.jobKey("JOB_" + jobId));//使任务处于等待状态,创建后不会执行
       } catch (SchedulerException e) {
       	e.printStackTrace();
           throw new MyException("创建任务失败", e);
       }
   }

   /**
    * 更新任务
    */
   public static void updateJob(Scheduler scheduler, Job scheduleJob) {
       //获取新的cron表达式
       CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
               .withMisfireHandlingInstructionDoNothing();

       Integer jobId = scheduleJob.getJobId();

       try {
           //拿到原有的trigger
           TriggerKey triggerKey = TriggerKey.triggerKey("TRIGGER_" + jobId);
           CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
           //为原有的trigger赋予新的cron表达式
           trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                   .withSchedule(cronScheduleBuilder).build();
           //执行原有的trigger更新
           scheduler.rescheduleJob(triggerKey, trigger);
       } catch (SchedulerException e) {
           e.printStackTrace();
           throw new MyException("更新定时任务失败", e);
       }
   }

   /**
    * 删除任务
    */
   public static void deleteJob(Scheduler scheduler, Long jobId) {
       try {
           scheduler.deleteJob(JobKey.jobKey("JOB_" + jobId));
       } catch (SchedulerException e) {
           e.printStackTrace();
           throw new MyException("删除定时任务失败", e);
       }
   }

   /**
    * 恢复任务
    */
   public static void resumeJob(Scheduler scheduler, Long jobId) {
       try {
           scheduler.resumeJob(JobKey.jobKey("JOB_" + jobId));
       } catch (SchedulerException e) {
           e.printStackTrace();
           throw new MyException("恢复定时任务失败", e);
       }
   }

   /**
    * 立即执行定时任务
    */
   public static void run(Scheduler scheduler, Long jobId) {
       try {
           //只执行一次并且不会改变任务的状态
           scheduler.triggerJob(JobKey.jobKey("JOB_" + jobId));
       } catch (SchedulerException e) {
           e.printStackTrace();
           throw new MyException("立即执行定时任务失败", e);
       }
   }

   /**
    * 暂停任务
    *
    * @param scheduler
    * @param jobId
    */
   public static void pauseJob(Scheduler scheduler, Long jobId) {
       try {
           scheduler.pauseJob(JobKey.jobKey("JOB_" + jobId));
       } catch (SchedulerException e) {
           e.printStackTrace();
           throw new MyException("暂停定时任务失败", e);
       }
   }
}
  • 任务执行(这个类中写你的真的任务,也就是逻辑代码)
public class QuartzJob extends QuartzJobBean {
   private Logger logger = LoggerFactory.getLogger(getClass());

   @Override
   protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
       System.err.println("执行quartz任务。。。。。");

       logger.info("任务已经执行了");

   }

}

以上配置完之后,应该就可以在项目中运行使用了!

可能会遇到的异常

我的mysql之前是5.1.6,启动会出现异常,换成5.1.26正常

上一篇:【调度任务----Quartz】Spring Quartz入门


下一篇:python 设置开机启动脚本