资讯

展开

SpringBoot定时任务---集成quartz实现定时任务(单实例和分布式两种方式)

作者:快盘下载 人气:

最为常用定时任务框架是Quartz;并且Spring也集成了Quartz的框架;Quartz不仅支持单实例方式还支持分布式方式。本文主要介绍Quartz;基础的Quartz的集成案例本;以及实现基于数据库的分布式任务管理和控制job生命周期。;pdai

SpringBoot定时任务 - 基础quartz实现方式 准备知识点 什么是QuartzQuartz的体系结构什么是Quartz持久化 实现案例 - 单实例方式实现案例 - 分布式方式 后端实现前端实现测试效果 示例源码参考文章

准备知识点

需要了解常用的Quartz框架。

什么是Quartz

来源百度百科, 官网地址;www.quartz-scheduler.org/

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目;它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个;百个;甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。

它的特点如下

纯java实现;可以作为独立的应用程序;也可以嵌入在另一个独立式应用程序运行强大的调度功能;Spring默认的调度框架;灵活可配置;作业持久化;调度环境持久化机制;可以保存并恢复调度现场。系统关闭数据不会丢失;灵活的应用方式;可以任意定义触发器的调度时间表;支持任务和调度各种组合;组件式监听器、各种插件、线程池等功能;多种存储方式等;分布式和集群能力;可以被实例化;一个Quartz集群中的每个节点作为一个独立的Quartz使用;通过相同的数据库表来感知到另一个Quartz应用

Quartz的体系结构

SpringBoot定时任务---集成quartz实现定时任务(单实例和分布式两种方式)

Job 表示一个工作;要执行的具体内容。JobDetail 表示一个具体的可执行的调度程序;Job 是这个可执行程调度程序所要执行的内容;另外 JobDetail 还包含了这个任务调度的方案和策略。Trigger 代表一个调度参数的配置;什么时候去调。Scheduler 代表一个调度容器;一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合;就可以被 Scheduler 容器调度了。

注; 上图来源于www.cnblogs.com/jijm123/p/1…

什么是Quartz持久化

为什么要持久化?

当程序突然被中断时;如断电;内存超出时;很有可能造成任务的丢失。 可以将调度信息存储到数据库里面;进行持久化;当程序被中断后;再次启动;仍然会保留中断之前的数据;继续执行;而并不是重新开始。

Quartz提供了两种持久化方式

Quartz提供两种基本作业存储类型:

RAMJobStore

在默认情况下Quartz将任务调度的运行信息保存在内存中;这种方法提供了最佳的性能;因为内存中数据访问最快。不足之处是缺乏数据的持久性;当程序路途停止或系统崩溃时;所有运行的信息都会丢失。

JobStoreTX

所有的任务信息都会保存到数据库中;可以控制事物;还有就是如果应用服务器关闭或者重启;任务信息都不会丢失;并且可以恢复因服务器关闭或者重启而导致执行失败的任务。

实现案例 - 单实例方式

本例将展示quartz实现单实例方式。

引入POM依赖
<dependency>
    <groupId>org.springFramework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
复制代码
定义Job

只需要继承QuartzJobBean;并重载executeInternal方法即可定义你自己的Job执行逻辑。

;Slf4j
public class HelloJob extends QuartzJobBean {

    ;Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        // get parameters
        context.getJobDetail().getJobDataMap().forEach(
                (k, v) -> log.info(;param, key:{}, value:{};, k, v)
        );
        // your logics
        log.info(;Hello Job执行时间: ; ; new Date());
    }
}
复制代码
配置Job

JobDetail, Trigger, Schedule(这里采用CronScheduleBuilder)

/**
 * ;author pdai
 */
;Configuration
public class QuartzConfig {

    ;Bean(;helloJob;)
    public JobDetail helloJobDetail() {
        return JobBuilder.newJob(HelloJob.class)
                .withIdentity(;DateTimeJob;)
                .usingJobData(;msg;, ;Hello Quartz;)
                .storeDurably()//即使没有Trigger关联时;也不需要删除该JobDetail
                .build();
    }

    ;Bean
    public Trigger printTimeJobTrigger() {
        // 每秒执行一次
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(;0/1 * * * * ?;);
        return TriggerBuilder.newTrigger()
                .forJob(helloJobDetail())
                .withIdentity(;quartzTaskService;)
                .withSchedule(cronScheduleBuilder)
                .build();
    }
}
复制代码
执行测试
2021-10-01 13:09:00.380  INFO 38484 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-10-01 13:09:00.391  INFO 38484 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-10-01 13:09:00.392  INFO 38484 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.50]
2021-10-01 13:09:00.526  INFO 38484 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-10-01 13:09:00.526  INFO 38484 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1424 ms
2021-10-01 13:09:00.866  INFO 38484 --- [           main] org.quartz.impl.StdSchedulerFactory      : Using default implementation for ThreadExecutor
2021-10-01 13:09:00.877  INFO 38484 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2021-10-01 13:09:00.877  INFO 38484 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v.2.3.2 created.
2021-10-01 13:09:00.878  INFO 38484 --- [           main] org.quartz.simpl.RAMJobStore             : RAMJobStore initialized.
2021-10-01 13:09:00.878  INFO 38484 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.3.2) ;quartzScheduler; with instanceId ;NON_CLUSTERED;
  Scheduler class: ;org.quartz.core.QuartzScheduler; - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool ;org.quartz.simpl.SimpleThreadPool; - with 10 threads.
  Using job-store ;org.quartz.simpl.RAMJobStore; - which does not support persistence. and is not clustered.

2021-10-01 13:09:00.878  INFO 38484 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler ;quartzScheduler; initialized from an externally provided properties instance.
2021-10-01 13:09:00.879  INFO 38484 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.3.2
2021-10-01 13:09:00.879  INFO 38484 --- [           main] org.quartz.core.QuartzScheduler          : JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory;6075b2d3
2021-10-01 13:09:00.922  INFO 38484 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ;;
2021-10-01 13:09:00.923  INFO 38484 --- [           main] o.s.s.quartz.SchedulerFactoryBean        : Starting Quartz Scheduler now
2021-10-01 13:09:00.923  INFO 38484 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler quartzScheduler_$_NON_CLUSTERED started.
2021-10-01 13:09:00.933  INFO 38484 --- [           main] tech.pdai.springboot.quartz.App          : Started App in 2.64 seconds (JVM running for 3.621)
2021-10-01 13:09:00.931  INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:00.933  INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:00 CST 2021
2021-10-01 13:09:01.001  INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:01.001  INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:01 CST 2021
2021-10-01 13:09:02.000  INFO 38484 --- [eduler_Worker-3] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:02.000  INFO 38484 --- [eduler_Worker-3] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:02 CST 2021
2021-10-01 13:09:03.000  INFO 38484 --- [eduler_Worker-4] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:03.001  INFO 38484 --- [eduler_Worker-4] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:03 CST 2021
2021-10-01 13:09:04.001  INFO 38484 --- [eduler_Worker-5] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:04.001  INFO 38484 --- [eduler_Worker-5] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:04 CST 2021
2021-10-01 13:09:05.002  INFO 38484 --- [eduler_Worker-6] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:05.003  INFO 38484 --- [eduler_Worker-6] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:05 CST 2021
2021-10-01 13:09:06.000  INFO 38484 --- [eduler_Worker-7] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:06.001  INFO 38484 --- [eduler_Worker-7] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:06 CST 2021
2021-10-01 13:09:07.002  INFO 38484 --- [eduler_Worker-8] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:07.002  INFO 38484 --- [eduler_Worker-8] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:07 CST 2021
2021-10-01 13:09:08.002  INFO 38484 --- [eduler_Worker-9] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:08.003  INFO 38484 --- [eduler_Worker-9] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:08 CST 2021
2021-10-01 13:09:09.000  INFO 38484 --- [duler_Worker-10] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:09.000  INFO 38484 --- [duler_Worker-10] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:09 CST 2021
2021-10-01 13:09:10.001  INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:10.002  INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:10 CST 2021
2021-10-01 13:09:11.014  INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob    : param, key:msg, value:Hello Quartz
2021-10-01 13:09:11.014  INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob    : Hello Job执行时间: Wed Oct 27 13:09:11 CST 2021
复制代码

实现案例 - 分布式方式

本例将展示quartz实现基于数据库的分布式任务管理;和控制job生命周期。

整体项目结构如下;

后端实现

pom.xml
<?xml version=;1.0; encoding=;UTF-8;?>
<project xmlns=;http://maven.apache.org/POM/4.0.0;
         xmlns:xsi=;http://www.w3.org/2001/XMLSchema-instance;
         xsi:schemaLocation=;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd;>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>tech.pdai</groupId>
    <artifactId>423-springboot-demo-schedule-quartz-cluster</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version><!--$NO-MVN-MAN-VER$-->
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>

</project>
复制代码
创建Schema

需要提前在MySQL中创建schema: quartz_jobs

#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;
# DROP TABLE IF EXISTS QRTZ_TASK_HISTORY;

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;

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;

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;

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;

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;

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;

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;

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;

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 TABLE QRTZ_TASK_HISTORY (
  SCHED_NAME VARCHAR(120) NOT NULL,
  INSTANCE_ID VARCHAR(200) NOT NULL,
  FIRE_ID VARCHAR(95) NOT NULL,
  TASK_NAME VARCHAR(200) NULL,
  TASK_GROUP VARCHAR(200) NULL,
  FIRED_TIME BIGINT(13) NULL,
  FIRED_WAY VARCHAR(8) NULL,
  COMPLETE_TIME BIGINT(13) NULL,
  EXPEND_TIME BIGINT(13) NULL,
  REFIRED INT NULL,
  EXEC_STATE VARCHAR(10) NULL,
  LOG TEXT NULL,
  PRIMARY KEY (FIRE_ID)
)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);

CREATE INDEX IDX_QRTZ_TK_S ON QRTZ_TASK_HISTORY(SCHED_NAME);

commit;
复制代码
application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/quartz_jobs?useUnicode=true&useSSL=false
    username: root
    password: xxxxxxxx
    driver-class-name: com.mysql.jdbc.Driver
  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
    #数据库方式
    job-store-type: jdbc
复制代码
定义JobDetails实体
/** 
 * ;author pdai
 *
 */
;Data
public class JobDetails{
	private String cronExpression;	
	private String jobClassName;	
	private String triggerGroupName;
	private String triggerName;
	private String jobGroupName;
	private String jobName;
	private Date nextFireTime;
	private Date previousFireTime;
	private Date startTime;
	private String timeZone;
	private String status;
}
复制代码
Job管理类
package tech.pdai.springboot.quartz.cluster.manager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import tech.pdai.springboot.quartz.cluster.entity.JobDetails;

/**
 * ;author pdai
 */
;Component
public class QuartzManager {

    ;Autowired
    private Scheduler sched;

    /**
     * 创建or更新任务;存在则更新不存在创建
     *
     * ;param jobClass     任务类
     * ;param jobName      任务名称
     * ;param jobGroupName 任务组名称
     * ;param jobCron      cron表达式
     */
    public void addOrUpdateJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobCron) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if (trigger==null) {
                addJob(jobClass, jobName, jobGroupName, jobCron);
            } else {
                if (trigger.getCronExpression().equals(jobCron)) {
                    return;
                }
                updateJob(jobName, jobGroupName, jobCron);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加一个job
     *
     * ;param jobClass     任务实现类
     * ;param jobName      任务名称
     * ;param jobGroupName 任务组名
     * ;param jobCron      cron表达式(如;0/5 * * * * ? )
     */
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobCron) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobCron)).startNow().build();

            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * ;param jobClass
     * ;param jobName
     * ;param jobGroupName
     * ;param jobTime
     */
    public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime) {
        addJob(jobClass, jobName, jobGroupName, jobTime, -1);
    }

    public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime, int jobTimes) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)// 任务名称和组构成任务key
                    .build();
            // 使用simpleTrigger规则
            Trigger trigger;
            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();
            }
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void updateJob(String jobName, String jobGroupName, String jobTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            // 重启触发器
            sched.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除任务一个job
     *
     * ;param jobName      任务名称
     * ;param jobGroupName 任务组名
     */
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            sched.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
            sched.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
            sched.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停一个job
     *
     * ;param jobName
     * ;param jobGroupName
     */
    public void pauseJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复一个job
     *
     * ;param jobName
     * ;param jobGroupName
     */
    public void resumeJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立即执行一个job
     *
     * ;param jobName
     * ;param jobGroupName
     */
    public void runAJobNow(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public PageInfo<JobDetails> queryAllJobBean(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<JobDetails> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = sched.getJobKeys(matcher);
            jobList = new ArrayList<>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    JobDetails jobDetails = new JobDetails();
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        jobDetails.setCronExpression(cronTrigger.getCronExpression());
                        jobDetails.setTimeZone(cronTrigger.getTimeZone().getDisplayName());
                    }
                    jobDetails.setTriggerGroupName(trigger.getKey().getName());
                    jobDetails.setTriggerName(trigger.getKey().getGroup());
                    jobDetails.setJobGroupName(jobKey.getGroup());
                    jobDetails.setJobName(jobKey.getName());
                    jobDetails.setStartTime(trigger.getStartTime());
                    jobDetails.setJobClassName(sched.getJobDetail(jobKey).getJobClass().getName());
                    jobDetails.setNextFireTime(trigger.getNextFireTime());
                    jobDetails.setPreviousFireTime(trigger.getPreviousFireTime());
                    jobDetails.setStatus(sched.getTriggerState(trigger.getKey()).name());
                    jobList.add(jobDetails);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return new PageInfo<>(jobList);
    }

    /**
     * 获取所有计划中的任务列表
     *
     * ;return
     */
    public List<Map<String, Object>> queryAllJob() {
        List<Map<String, Object>> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = sched.getJobKeys(matcher);
            jobList = new ArrayList<>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = sched.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:; ; trigger.getKey());
                    Trigger.TriggerState triggerState = sched.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();
        }
        return jobList;
    }

    /**
     * 获取所有正在运行的job
     *
     * ;return
     */
    public List<Map<String, Object>> queryRunJon() {
        List<Map<String, Object>> jobList = null;
        try {
            List<JobExecutionContext> executingJobs = sched.getCurrentlyExecutingJobs();
            jobList = new ArrayList<>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                Map<String, Object> map = new HashMap<>();
                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:; ; trigger.getKey());
                Trigger.TriggerState triggerState = sched.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();
        }
        return jobList;
    }
}
复制代码
Job控制器接口
package tech.pdai.springboot.quartz.cluster.controller;

import java.util.HashMap;
import java.util.Map;

import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tech.pdai.springboot.quartz.cluster.entity.JobDetails;
import tech.pdai.springboot.quartz.cluster.manager.QuartzManager;


/**
 * ;author pdai
 */
;RestController
;RequestMapping(value = ;/job;)
public class JobController {

    ;Autowired
    private QuartzManager qtzManager;

    ;SuppressWarnings(;unchecked;)
    private static Class<? extends QuartzJobBean> getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Class<? extends QuartzJobBean>) class1;
    }

    /**
     * ;param jobClassName
     * ;param jobGroupName
     * ;param cronExpression
     * ;throws Exception
     */
    ;PostMapping(value = ;/addjob;)
    public void addjob(;RequestParam(value = ;jobClassName;) String jobClassName,
                       ;RequestParam(value = ;jobGroupName;) String jobGroupName,
                       ;RequestParam(value = ;cronExpression;) String cronExpression) throws Exception {
        qtzManager.addOrUpdateJob(getClass(jobClassName), jobClassName, jobGroupName, cronExpression);
    }

    /**
     * ;param jobClassName
     * ;param jobGroupName
     * ;throws Exception
     */
    ;PostMapping(value = ;/pausejob;)
    public void pausejob(;RequestParam(value = ;jobClassName;) String jobClassName,
                         ;RequestParam(value = ;jobGroupName;) String jobGroupName) throws Exception {
        qtzManager.pauseJob(jobClassName, jobGroupName);
    }

    /**
     * ;param jobClassName
     * ;param jobGroupName
     * ;throws Exception
     */
    ;PostMapping(value = ;/resumejob;)
    public void resumejob(;RequestParam(value = ;jobClassName;) String jobClassName,
                          ;RequestParam(value = ;jobGroupName;) String jobGroupName) throws Exception {
        qtzManager.resumeJob(jobClassName, jobGroupName);
    }

    /**
     * ;param jobClassName
     * ;param jobGroupName
     * ;param cronExpression
     * ;throws Exception
     */
    ;PostMapping(value = ;/reschedulejob;)
    public void rescheduleJob(;RequestParam(value = ;jobClassName;) String jobClassName,
                              ;RequestParam(value = ;jobGroupName;) String jobGroupName,
                              ;RequestParam(value = ;cronExpression;) String cronExpression) throws Exception {
        qtzManager.addOrUpdateJob(getClass(jobClassName), jobClassName, jobGroupName, cronExpression);
    }

    /**
     * ;param jobClassName
     * ;param jobGroupName
     * ;throws Exception
     */
    ;PostMapping(value = ;/deletejob;)
    public void deletejob(;RequestParam(value = ;jobClassName;) String jobClassName,
                          ;RequestParam(value = ;jobGroupName;) String jobGroupName) throws Exception {
        qtzManager.deleteJob(jobClassName, jobGroupName);
    }

    /**
     * ;param pageNum
     * ;param pageSize
     * ;return
     */
    ;GetMapping(value = ;/queryjob;)
    public Map<String, Object> queryjob(;RequestParam(value = ;pageNum;) Integer pageNum,
                                        ;RequestParam(value = ;pageSize;) Integer pageSize) {
        PageInfo<JobDetails> jobAndTrigger = qtzManager.queryAllJobBean(pageNum, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(;JobAndTrigger;, jobAndTrigger);
        map.put(;number;, jobAndTrigger.getTotal());
        return map;
    }
}
复制代码
定义具体的Job
package tech.pdai.springboot.quartz.cluster.job;

import java.util.Date;

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

;Slf4j
public class HelloJob extends QuartzJobBean {

    ;Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        // get parameters
        context.getJobDetail().getJobDataMap().forEach(
                (k, v) -> log.info(;param, key:{}, value:{};, k, v)
        );
        // your logics
        log.info(;Hello Job执行时间: ; ; new Date());
    }
}
复制代码

前端实现

简单用VueJS 写个页面测试

<!DOCTYPE html>
<html>
<head>
<meta charset=;UTF-8;>
	<title>QuartzDemo</title>
	<link rel=;stylesheet; href=;https://unpkg.com/element-ui;2.0.5/lib/theme-chalk/index.css;>
	<script src=;https://unpkg.com/vue/dist/vue.js;></script>
	<script src=;http://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.js;></script>
	<script src=;https://unpkg.com/element-ui;2.0.5/lib/index.js;></script>
	
	<style>      
      #top {
	      background:#20A0FF;
	      padding:5px;
	      Overflow:hidden
      }
	</style>
	
</head>
<body>
    <div id=;test;>		        

		<div id=;top;>			
				<el-button type=;text; ;click=;search; style=;color:white;>查询</el-button>	
				<el-button type=;text; ;click=;handleadd; style=;color:white;>添加</el-button>	
			</span>						
		</div>	
				
		<br/>

        <div style=;margin-top:15px;>	

		  <el-table
		    ref=;testTable;		  
		    :data=;tableData;
		    style=;width:100%
		    border
		    >
		    <el-table-column
		      prop=;status;
		      label=;任务状态;
		      sortable
		      show-overflow-tooltip>
		    </el-table-column>
		    
		    <el-table-column
		      prop=;jobName;
		      label=;任务名称;
		      sortable
		      show-overflow-tooltip>
		    </el-table-column>
		    
		    <el-table-column
		      prop=;jobGroupName;
		      label=;任务所在组;
		      sortable>
		    </el-table-column>
		    
   		    <el-table-column
		      prop=;jobClassName;
		      label=;任务类名;
		      sortable>
		    </el-table-column>
		    
   		    <el-table-column
		      prop=;triggerName;
		      label=;触发器名称;
		      sortable>
		    </el-table-column>
		    
		    <el-table-column
		      prop=;triggerGroupName;
		      label=;触发器所在组;
		      sortable>
		    </el-table-column>
		    
		    <el-table-column
		      prop=;cronExpression;
		      label=;表达式;
		      sortable>
		    </el-table-column>
		    
		    <el-table-column
		      prop=;timeZone;
		      label=;时区;
		      sortable>
		    </el-table-column>
		    
	        <el-table-column label=;操作; width=;300;>
		      <template scope=;scope;>
		      	<el-button
		          size=;small;
		          type=;warning;
		          ;click=;handlePause(scope.$index, scope.row);>暂停</el-button>
		          
		        <el-button
		          size=;small;
		          type=;info;
		          ;click=;handleResume(scope.$index, scope.row);>恢复</el-button>
		          
		        <el-button
		          size=;small;
		          type=;danger;
		          ;click=;handleDelete(scope.$index, scope.row);>删除</el-button>
		          
		        <el-button
		          size=;small;
		          type=;success;
		          ;click=;handleUpdate(scope.$index, scope.row);>修改</el-button>
		      </template>
		    </el-table-column>
		  </el-table>
		  
		  <div align=;center;>
			  <el-pagination
			      ;size-change=;handleSizeChange;
			      ;current-change=;handleCurrentChange;
			      :current-page=;currentPage;
			      :page-sizes=;[10, 20, 30, 40];
			      :page-size=;pagesize;
			      layout=;total, sizes, prev, pager, next, jumper;
			      :total=;totalCount;>
			  </el-pagination>
		  </div>
		</div> 
		
		<el-dialog title=;添加任务; :visible.sync=;dialogFormVisible;>
		  <el-form :model=;form;>
		    <el-form-item label=;任务名称; label-width=;120px; style=;width:35%>
		      <el-input v-model=;form.jobName; auto-complete=;off;></el-input>
		    </el-form-item>	    
		    <el-form-item label=;任务分组; label-width=;120px; style=;width:35%>
		      <el-input v-model=;form.jobGroup; auto-complete=;off;></el-input>
		    </el-form-item>
		    <el-form-item label=;表达式; label-width=;120px; style=;width:35%>
		      <el-input v-model=;form.cronExpression; auto-complete=;off;></el-input>
		    </el-form-item>
		  </el-form>
		  <div slot=;footer; class=;dialog-footer;>
		    <el-button ;click=;dialogFormVisible = false;>取 消</el-button>
		    <el-button type=;primary; ;click=;add;>确 定</el-button>
		  </div>
		</el-dialog>
		
		<el-dialog title=;修改任务; :visible.sync=;updateFormVisible;>
		  <el-form :model=;updateform;>
		    <el-form-item label=;表达式; label-width=;120px; style=;width:35%>
		      <el-input v-model=;updateform.cronExpression; auto-complete=;off;></el-input>
		    </el-form-item>
		  </el-form>
		  <div slot=;footer; class=;dialog-footer;>
		    <el-button ;click=;updateFormVisible = false;>取 消</el-button>
		    <el-button type=;primary; ;click=;update;>确 定</el-button>
		  </div>
		</el-dialog>
		
    </div>
	
    <footer align=;center;>
        <p>&copy; Quartz 任务管理</p>
    </footer>

	<script>
	var vue = new Vue({			
			el:;#test;,
		    data: {		  
		    	//表格当前页数据
		    	tableData: [],
		        
		        //请求的URL
		        url:;job/queryjob;,
		        
		        //默认每页数据量
		        pagesize: 10,		        
		        
		        //当前页码
		        currentPage: 1,
		        
		        //查询的页码
		        start: 1,
		        
		        //默认数据总数
		        totalCount: 1000,
		        
		        //添加对话框默认可见性
		        dialogFormVisible: false,
		        
		        //修改对话框默认可见性
		        updateFormVisible: false,
		        
		        //提交的表单
		        form: {
		        	jobName: ;;,
		        	jobGroup: ;;,
		        	cronExpression: ;;,
		          },
		          
		        updateform: {
		        	jobName: ;;,
		        	jobGroup: ;;,
		        	cronExpression: ;;,
		        },
		    },

		    methods: {
		    	
		        //从服务器读取数据
				loadData: function(pageNum, pageSize){					
					this.$http.get(;job/queryjob?; ; ;pageNum=; ;  pageNum ; ;&pageSize=; ; pageSize).then(function(res){
						console.log(res)
                		this.tableData = res.body.JobAndTrigger.list;
                		this.totalCount = res.body.number;
                	},function(){
                  		console.log(;failed;);
                	});					
				},			    		        
				      
		        //单行删除
			    handleDelete: function(index, row) {
					this.$http.post(;job/deletejob;,{;jobClassName;:row.jobName,;jobGroupName;:row.jobGroupName},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log(;failed;);
		            });
		        },
		        
		        //暂停任务
		        handlePause: function(index, row){
		        	this.$http.post(;job/pausejob;,{;jobClassName;:row.jobName,;jobGroupName;:row.jobGroupName},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log(;failed;);
		            });
		        },
		        
		        //恢复任务
		        handleResume: function(index, row){
		        	this.$http.post(;job/resumejob;,{;jobClassName;:row.jobName,;jobGroupName;:row.jobGroupName},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log(;failed;);
		            });
		        },
		        
		        //搜索
		        search: function(){
		        	this.loadData(this.currentPage, this.pagesize);
		        },
		        
		        //弹出对话框
		        handleadd: function(){		                
		            this.dialogFormVisible = true;	              
		        },
		        
		        //添加
		        add: function(){
		        	this.$http.post(;job/addjob;,{;jobClassName;:this.form.jobName,;jobGroupName;:this.form.jobGroup,;cronExpression;:this.form.cronExpression},{emulateJSON: true}).then(function(res){
        				this.loadData(this.currentPage, this.pagesize);
        				this.dialogFormVisible = false;
                    },function(){
                        console.log(;failed;);
                    });
		        },
		        
		        //更新
		        handleUpdate: function(index, row){
		        	console.log(row)
		        	this.updateFormVisible = true;
		        	this.updateform.jobName = row.jobClassName;
		        	this.updateform.jobGroup = row.jobGroupName;
		        },
		        
		        //更新任务
		        update: function(){
		        	this.$http.post
		        	(;job/reschedulejob;,
		        			{;jobClassName;:this.updateform.jobName,
		        			 ;jobGroupName;:this.updateform.jobGroup,
		        			 ;cronExpression;:this.updateform.cronExpression
		        			 },{emulateJSON: true}
		        	).then(function(res){
		        		this.loadData(this.currentPage, this.pagesize);
        				this.updateFormVisible = false;
		        	},function(){
                        console.log(;failed;);
                    });
		    
		        },
		      
		        //每页显示数据量变更
		        handleSizeChange: function(val) {
		            this.pagesize = val;
		            this.loadData(this.currentPage, this.pagesize);
		        },
		        
		        //页码变更
		        handleCurrentChange: function(val) {
		            this.currentPage = val;
		            this.loadData(this.currentPage, this.pagesize);
		        },	      
		        		        
		    },	    
		    
		    
		  });
	
		  //载入数据
    	  vue.loadData(vue.currentPage, vue.pagesize);
	</script>  
	
</body>
</html>
复制代码

测试效果

(PS: 这里的任务名称需要改成你自己的完整类名称)

展示正在运行的Jobs:

集成quartz实现定时任务(单实例和分布式两种方式)

增加新的Job:

SpringBoot定时任务

Jobs持久化在数据库:

-

示例源码

github.com/realpdai/te…

更多内容

告别碎片化学习;无套路一站式体系化学习后端开发: Java 全栈知识体系 https://pdai.tech

来源;https://juejin.cn/post/7126687148371083294#

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!