经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
SpringBoot集成quartz实现定时任务详解
来源:jb51  时间:2022/8/1 11:08:39  对本文有异议

准备知识点

需要了解常用的Quartz框架。

什么是Quartz

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

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

它的特点如下

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

Quartz的体系结构

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

什么是Quartz持久化

为什么要持久化

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

Quartz提供了两种持久化方式

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

RAMJobStore

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

JobStoreTX

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

实现案例 - 单实例方式

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

引入POM依赖

定义Job

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

  1. @Slf4j
  2. public class HelloJob extends QuartzJobBean {
  3.  
  4. @Override
  5. protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  6. // get parameters
  7. context.getJobDetail().getJobDataMap().forEach(
  8. (k, v) -> log.info("param, key:{}, value:{}", k, v)
  9. );
  10. // your logics
  11. log.info("Hello Job执行时间: " + new Date());
  12. }
  13. }

配置Job

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

  1. /**
  2. * @author pdai
  3. */
  4. @Configuration
  5. public class QuartzConfig {
  6.  
  7. @Bean("helloJob")
  8. public JobDetail helloJobDetail() {
  9. return JobBuilder.newJob(HelloJob.class)
  10. .withIdentity("DateTimeJob")
  11. .usingJobData("msg", "Hello Quartz")
  12. .storeDurably()//即使没有Trigger关联时,也不需要删除该JobDetail
  13. .build();
  14. }
  15.  
  16. @Bean
  17. public Trigger printTimeJobTrigger() {
  18. // 每秒执行一次
  19. CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
  20. return TriggerBuilder.newTrigger()
  21. .forJob(helloJobDetail())
  22. .withIdentity("quartzTaskService")
  23. .withSchedule(cronScheduleBuilder)
  24. .build();
  25. }
  26. }

执行测试

  1. 2021-10-01 13:09:00.380 INFO 38484 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
  2. 2021-10-01 13:09:00.391 INFO 38484 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
  3. 2021-10-01 13:09:00.392 INFO 38484 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.50]
  4. 2021-10-01 13:09:00.526 INFO 38484 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
  5. 2021-10-01 13:09:00.526 INFO 38484 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1424 ms
  6. 2021-10-01 13:09:00.866 INFO 38484 --- [ main] org.quartz.impl.StdSchedulerFactory : Using default implementation for ThreadExecutor
  7. 2021-10-01 13:09:00.877 INFO 38484 --- [ main] org.quartz.core.SchedulerSignalerImpl : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
  8. 2021-10-01 13:09:00.877 INFO 38484 --- [ main] org.quartz.core.QuartzScheduler : Quartz Scheduler v.2.3.2 created.
  9. 2021-10-01 13:09:00.878 INFO 38484 --- [ main] org.quartz.simpl.RAMJobStore : RAMJobStore initialized.
  10. 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'
  11. Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  12. NOT STARTED.
  13. Currently in standby mode.
  14. Number of jobs executed: 0
  15. Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  16. Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
  17.  
  18. 2021-10-01 13:09:00.878 INFO 38484 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
  19. 2021-10-01 13:09:00.879 INFO 38484 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: 2.3.2
  20. 2021-10-01 13:09:00.879 INFO 38484 --- [ main] org.quartz.core.QuartzScheduler : JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@6075b2d3
  21. 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 ''
  22. 2021-10-01 13:09:00.923 INFO 38484 --- [ main] o.s.s.quartz.SchedulerFactoryBean : Starting Quartz Scheduler now
  23. 2021-10-01 13:09:00.923 INFO 38484 --- [ main] org.quartz.core.QuartzScheduler : Scheduler quartzScheduler_$_NON_CLUSTERED started.
  24. 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)
  25. 2021-10-01 13:09:00.931 INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  26. 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
  27. 2021-10-01 13:09:01.001 INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  28. 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
  29. 2021-10-01 13:09:02.000 INFO 38484 --- [eduler_Worker-3] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  30. 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
  31. 2021-10-01 13:09:03.000 INFO 38484 --- [eduler_Worker-4] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  32. 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
  33. 2021-10-01 13:09:04.001 INFO 38484 --- [eduler_Worker-5] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  34. 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
  35. 2021-10-01 13:09:05.002 INFO 38484 --- [eduler_Worker-6] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  36. 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
  37. 2021-10-01 13:09:06.000 INFO 38484 --- [eduler_Worker-7] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  38. 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
  39. 2021-10-01 13:09:07.002 INFO 38484 --- [eduler_Worker-8] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  40. 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
  41. 2021-10-01 13:09:08.002 INFO 38484 --- [eduler_Worker-9] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  42. 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
  43. 2021-10-01 13:09:09.000 INFO 38484 --- [duler_Worker-10] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  44. 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
  45. 2021-10-01 13:09:10.001 INFO 38484 --- [eduler_Worker-1] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  46. 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
  47. 2021-10-01 13:09:11.014 INFO 38484 --- [eduler_Worker-2] t.pdai.springboot.quartz.job.HelloJob : param, key:msg, value:Hello Quartz
  48. 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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.5.3</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11.  
  12. <modelVersion>4.0.0</modelVersion>
  13. <groupId>tech.pdai</groupId>
  14. <artifactId>423-springboot-demo-schedule-quartz-cluster</artifactId>
  15. <version>1.0-SNAPSHOT</version>
  16.  
  17. <properties>
  18. <maven.compiler.source>8</maven.compiler.source>
  19. <maven.compiler.target>8</maven.compiler.target>
  20. </properties>
  21.  
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-quartz</artifactId>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.boot</groupId>
  33. <artifactId>spring-boot-starter-data-jpa</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>mysql</groupId>
  37. <artifactId>mysql-connector-java</artifactId>
  38. <version>5.1.42</version><!--$NO-MVN-MAN-VER$-->
  39. <scope>runtime</scope>
  40. </dependency>
  41. <dependency>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-starter-test</artifactId>
  44. <scope>test</scope>
  45. </dependency>
  46.  
  47. <dependency>
  48. <groupId>org.projectlombok</groupId>
  49. <artifactId>lombok</artifactId>
  50. <version>1.18.20</version>
  51. <optional>true</optional>
  52. </dependency>
  53.  
  54. <dependency>
  55. <groupId>com.github.pagehelper</groupId>
  56. <artifactId>pagehelper</artifactId>
  57. <version>5.0.0</version>
  58. </dependency>
  59. </dependencies>
  60.  
  61. </project>

创建Schema

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

  1. # DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
  2. # DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
  3. # DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
  4. # DROP TABLE IF EXISTS QRTZ_LOCKS;
  5. # DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
  6. # DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
  7. # DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
  8. # DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
  9. # DROP TABLE IF EXISTS QRTZ_TRIGGERS;
  10. # DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
  11. # DROP TABLE IF EXISTS QRTZ_CALENDARS;
  12. # DROP TABLE IF EXISTS QRTZ_TASK_HISTORY;
  13.  
  14. CREATE TABLE QRTZ_JOB_DETAILS(
  15. SCHED_NAME VARCHAR(120) NOT NULL,
  16. JOB_NAME VARCHAR(200) NOT NULL,
  17. JOB_GROUP VARCHAR(200) NOT NULL,
  18. DESCRIPTION VARCHAR(250) NULL,
  19. JOB_CLASS_NAME VARCHAR(250) NOT NULL,
  20. IS_DURABLE VARCHAR(1) NOT NULL,
  21. IS_NONCONCURRENT VARCHAR(1) NOT NULL,
  22. IS_UPDATE_DATA VARCHAR(1) NOT NULL,
  23. REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
  24. JOB_DATA BLOB NULL,
  25. PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
  26. ENGINE=InnoDB;
  27.  
  28. CREATE TABLE QRTZ_TRIGGERS (
  29. SCHED_NAME VARCHAR(120) NOT NULL,
  30. TRIGGER_NAME VARCHAR(200) NOT NULL,
  31. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  32. JOB_NAME VARCHAR(200) NOT NULL,
  33. JOB_GROUP VARCHAR(200) NOT NULL,
  34. DESCRIPTION VARCHAR(250) NULL,
  35. NEXT_FIRE_TIME BIGINT(13) NULL,
  36. PREV_FIRE_TIME BIGINT(13) NULL,
  37. PRIORITY INTEGER NULL,
  38. TRIGGER_STATE VARCHAR(16) NOT NULL,
  39. TRIGGER_TYPE VARCHAR(8) NOT NULL,
  40. START_TIME BIGINT(13) NOT NULL,
  41. END_TIME BIGINT(13) NULL,
  42. CALENDAR_NAME VARCHAR(200) NULL,
  43. MISFIRE_INSTR SMALLINT(2) NULL,
  44. JOB_DATA BLOB NULL,
  45. PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  46. FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
  47. REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
  48. ENGINE=InnoDB;
  49.  
  50. CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
  51. SCHED_NAME VARCHAR(120) NOT NULL,
  52. TRIGGER_NAME VARCHAR(200) NOT NULL,
  53. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  54. REPEAT_COUNT BIGINT(7) NOT NULL,
  55. REPEAT_INTERVAL BIGINT(12) NOT NULL,
  56. TIMES_TRIGGERED BIGINT(10) NOT NULL,
  57. PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  58. FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  59. REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  60. ENGINE=InnoDB;
  61.  
  62. CREATE TABLE QRTZ_CRON_TRIGGERS (
  63. SCHED_NAME VARCHAR(120) NOT NULL,
  64. TRIGGER_NAME VARCHAR(200) NOT NULL,
  65. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  66. CRON_EXPRESSION VARCHAR(120) NOT NULL,
  67. TIME_ZONE_ID VARCHAR(80),
  68. PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  69. FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  70. REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  71. ENGINE=InnoDB;
  72.  
  73. CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  74. (
  75. SCHED_NAME VARCHAR(120) NOT NULL,
  76. TRIGGER_NAME VARCHAR(200) NOT NULL,
  77. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  78. STR_PROP_1 VARCHAR(512) NULL,
  79. STR_PROP_2 VARCHAR(512) NULL,
  80. STR_PROP_3 VARCHAR(512) NULL,
  81. INT_PROP_1 INT NULL,
  82. INT_PROP_2 INT NULL,
  83. LONG_PROP_1 BIGINT NULL,
  84. LONG_PROP_2 BIGINT NULL,
  85. DEC_PROP_1 NUMERIC(13,4) NULL,
  86. DEC_PROP_2 NUMERIC(13,4) NULL,
  87. BOOL_PROP_1 VARCHAR(1) NULL,
  88. BOOL_PROP_2 VARCHAR(1) NULL,
  89. PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  90. FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  91. REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  92. ENGINE=InnoDB;
  93.  
  94. CREATE TABLE QRTZ_BLOB_TRIGGERS (
  95. SCHED_NAME VARCHAR(120) NOT NULL,
  96. TRIGGER_NAME VARCHAR(200) NOT NULL,
  97. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  98. BLOB_DATA BLOB NULL,
  99. PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  100. INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
  101. FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  102. REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  103. ENGINE=InnoDB;
  104.  
  105. CREATE TABLE QRTZ_CALENDARS (
  106. SCHED_NAME VARCHAR(120) NOT NULL,
  107. CALENDAR_NAME VARCHAR(200) NOT NULL,
  108. CALENDAR BLOB NOT NULL,
  109. PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
  110. ENGINE=InnoDB;
  111.  
  112. CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
  113. SCHED_NAME VARCHAR(120) NOT NULL,
  114. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  115. PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
  116. ENGINE=InnoDB;
  117.  
  118. CREATE TABLE QRTZ_FIRED_TRIGGERS (
  119. SCHED_NAME VARCHAR(120) NOT NULL,
  120. ENTRY_ID VARCHAR(95) NOT NULL,
  121. TRIGGER_NAME VARCHAR(200) NOT NULL,
  122. TRIGGER_GROUP VARCHAR(200) NOT NULL,
  123. INSTANCE_NAME VARCHAR(200) NOT NULL,
  124. FIRED_TIME BIGINT(13) NOT NULL,
  125. SCHED_TIME BIGINT(13) NOT NULL,
  126. PRIORITY INTEGER NOT NULL,
  127. STATE VARCHAR(16) NOT NULL,
  128. JOB_NAME VARCHAR(200) NULL,
  129. JOB_GROUP VARCHAR(200) NULL,
  130. IS_NONCONCURRENT VARCHAR(1) NULL,
  131. REQUESTS_RECOVERY VARCHAR(1) NULL,
  132. PRIMARY KEY (SCHED_NAME,ENTRY_ID))
  133. ENGINE=InnoDB;
  134.  
  135. CREATE TABLE QRTZ_SCHEDULER_STATE (
  136. SCHED_NAME VARCHAR(120) NOT NULL,
  137. INSTANCE_NAME VARCHAR(200) NOT NULL,
  138. LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
  139. CHECKIN_INTERVAL BIGINT(13) NOT NULL,
  140. PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
  141. ENGINE=InnoDB;
  142.  
  143. CREATE TABLE QRTZ_LOCKS (
  144. SCHED_NAME VARCHAR(120) NOT NULL,
  145. LOCK_NAME VARCHAR(40) NOT NULL,
  146. PRIMARY KEY (SCHED_NAME,LOCK_NAME))
  147. ENGINE=InnoDB;
  148.  
  149. CREATE TABLE QRTZ_TASK_HISTORY (
  150. SCHED_NAME VARCHAR(120) NOT NULL,
  151. INSTANCE_ID VARCHAR(200) NOT NULL,
  152. FIRE_ID VARCHAR(95) NOT NULL,
  153. TASK_NAME VARCHAR(200) NULL,
  154. TASK_GROUP VARCHAR(200) NULL,
  155. FIRED_TIME BIGINT(13) NULL,
  156. FIRED_WAY VARCHAR(8) NULL,
  157. COMPLETE_TIME BIGINT(13) NULL,
  158. EXPEND_TIME BIGINT(13) NULL,
  159. REFIRED INT NULL,
  160. EXEC_STATE VARCHAR(10) NULL,
  161. LOG TEXT NULL,
  162. PRIMARY KEY (FIRE_ID)
  163. )ENGINE=InnoDB;
  164.  
  165. CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
  166. CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
  167.  
  168. CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  169. CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
  170. CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
  171. CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  172. CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
  173. CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  174. CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  175. CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
  176. CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
  177. CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
  178. CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
  179. CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
  180.  
  181. CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
  182. CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
  183. CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  184. CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
  185. CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
  186. CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  187.  
  188. CREATE INDEX IDX_QRTZ_TK_S ON QRTZ_TASK_HISTORY(SCHED_NAME);
  189.  
  190. commit;

application.yml

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/quartz_jobs?useUnicode=true&useSSL=false
  4. username: root
  5. password: xxxxxxxx
  6. driver-class-name: com.mysql.jdbc.Driver
  7. quartz:
  8. #相关属性配置
  9. properties:
  10. org:
  11. quartz:
  12. scheduler:
  13. instanceName: clusteredScheduler
  14. instanceId: AUTO
  15. jobStore:
  16. class: org.quartz.impl.jdbcjobstore.JobStoreTX
  17. driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  18. tablePrefix: QRTZ_
  19. isClustered: true
  20. clusterCheckinInterval: 10000
  21. useProperties: false
  22. threadPool:
  23. class: org.quartz.simpl.SimpleThreadPool
  24. threadCount: 10
  25. threadPriority: 5
  26. threadsInheritContextClassLoaderOfInitializingThread: true
  27. #数据库方式
  28. job-store-type: jdbc

定义JobDetails实体

  1. /**
  2. * @author pdai
  3. *
  4. */
  5. @Data
  6. public class JobDetails{
  7. private String cronExpression;
  8. private String jobClassName;
  9. private String triggerGroupName;
  10. private String triggerName;
  11. private String jobGroupName;
  12. private String jobName;
  13. private Date nextFireTime;
  14. private Date previousFireTime;
  15. private Date startTime;
  16. private String timeZone;
  17. private String status;
  18. }

Job管理类

  1. package tech.pdai.springboot.quartz.cluster.manager;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Set;
  8.  
  9. import com.github.pagehelper.PageHelper;
  10. import com.github.pagehelper.PageInfo;
  11. import org.quartz.CronScheduleBuilder;
  12. import org.quartz.CronTrigger;
  13. import org.quartz.DateBuilder;
  14. import org.quartz.DateBuilder.IntervalUnit;
  15. import org.quartz.Job;
  16. import org.quartz.JobBuilder;
  17. import org.quartz.JobDetail;
  18. import org.quartz.JobExecutionContext;
  19. import org.quartz.JobKey;
  20. import org.quartz.Scheduler;
  21. import org.quartz.SchedulerException;
  22. import org.quartz.SimpleScheduleBuilder;
  23. import org.quartz.Trigger;
  24. import org.quartz.TriggerBuilder;
  25. import org.quartz.TriggerKey;
  26. import org.quartz.impl.matchers.GroupMatcher;
  27. import org.springframework.beans.factory.annotation.Autowired;
  28. import org.springframework.scheduling.quartz.QuartzJobBean;
  29. import org.springframework.stereotype.Component;
  30. import tech.pdai.springboot.quartz.cluster.entity.JobDetails;
  31.  
  32. /**
  33. * @author pdai
  34. */
  35. @Component
  36. public class QuartzManager {
  37.  
  38. @Autowired
  39. private Scheduler sched;
  40.  
  41. /**
  42. * 创建or更新任务,存在则更新不存在创建
  43. *
  44. * @param jobClass 任务类
  45. * @param jobName 任务名称
  46. * @param jobGroupName 任务组名称
  47. * @param jobCron cron表达式
  48. */
  49. public void addOrUpdateJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobCron) {
  50. try {
  51. TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
  52. CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
  53. if (trigger==null) {
  54. addJob(jobClass, jobName, jobGroupName, jobCron);
  55. } else {
  56. if (trigger.getCronExpression().equals(jobCron)) {
  57. return;
  58. }
  59. updateJob(jobName, jobGroupName, jobCron);
  60. }
  61. } catch (SchedulerException e) {
  62. e.printStackTrace();
  63. }
  64. }
  65.  
  66. /**
  67. * 增加一个job
  68. *
  69. * @param jobClass 任务实现类
  70. * @param jobName 任务名称
  71. * @param jobGroupName 任务组名
  72. * @param jobCron cron表达式(如:0/5 * * * * ? )
  73. */
  74. public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobCron) {
  75. try {
  76. JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
  77. Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
  78. .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
  79. .withSchedule(CronScheduleBuilder.cronSchedule(jobCron)).startNow().build();
  80.  
  81. sched.scheduleJob(jobDetail, trigger);
  82. if (!sched.isShutdown()) {
  83. sched.start();
  84. }
  85. } catch (SchedulerException e) {
  86. e.printStackTrace();
  87. }
  88. }
  89.  
  90. /**
  91. * @param jobClass
  92. * @param jobName
  93. * @param jobGroupName
  94. * @param jobTime
  95. */
  96. public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime) {
  97. addJob(jobClass, jobName, jobGroupName, jobTime, -1);
  98. }
  99.  
  100. public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime, int jobTimes) {
  101. try {
  102. JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)// 任务名称和组构成任务key
  103. .build();
  104. // 使用simpleTrigger规则
  105. Trigger trigger;
  106. if (jobTimes < 0) {
  107. trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
  108. .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
  109. .startNow().build();
  110. } else {
  111. trigger = TriggerBuilder
  112. .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
  113. .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
  114. .startNow().build();
  115. }
  116. sched.scheduleJob(jobDetail, trigger);
  117. if (!sched.isShutdown()) {
  118. sched.start();
  119. }
  120. } catch (SchedulerException e) {
  121. e.printStackTrace();
  122. }
  123. }
  124.  
  125. public void updateJob(String jobName, String jobGroupName, String jobTime) {
  126. try {
  127. TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
  128. CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
  129. trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
  130. .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
  131. // 重启触发器
  132. sched.rescheduleJob(triggerKey, trigger);
  133. } catch (SchedulerException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137.  
  138. /**
  139. * 删除任务一个job
  140. *
  141. * @param jobName 任务名称
  142. * @param jobGroupName 任务组名
  143. */
  144. public void deleteJob(String jobName, String jobGroupName) {
  145. try {
  146. sched.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
  147. sched.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
  148. sched.deleteJob(new JobKey(jobName, jobGroupName));
  149. } catch (Exception e) {
  150. e.printStackTrace();
  151. }
  152. }
  153.  
  154. /**
  155. * 暂停一个job
  156. *
  157. * @param jobName
  158. * @param jobGroupName
  159. */
  160. public void pauseJob(String jobName, String jobGroupName) {
  161. try {
  162. JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
  163. sched.pauseJob(jobKey);
  164. } catch (SchedulerException e) {
  165. e.printStackTrace();
  166. }
  167. }
  168.  
  169. /**
  170. * 恢复一个job
  171. *
  172. * @param jobName
  173. * @param jobGroupName
  174. */
  175. public void resumeJob(String jobName, String jobGroupName) {
  176. try {
  177. JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
  178. sched.resumeJob(jobKey);
  179. } catch (SchedulerException e) {
  180. e.printStackTrace();
  181. }
  182. }
  183.  
  184. /**
  185. * 立即执行一个job
  186. *
  187. * @param jobName
  188. * @param jobGroupName
  189. */
  190. public void runAJobNow(String jobName, String jobGroupName) {
  191. try {
  192. JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
  193. sched.triggerJob(jobKey);
  194. } catch (SchedulerException e) {
  195. e.printStackTrace();
  196. }
  197. }
  198.  
  199. public PageInfo<JobDetails> queryAllJobBean(int pageNum, int pageSize) {
  200. PageHelper.startPage(pageNum, pageSize);
  201. List<JobDetails> jobList = null;
  202. try {
  203. GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
  204. Set<JobKey> jobKeys = sched.getJobKeys(matcher);
  205. jobList = new ArrayList<>();
  206. for (JobKey jobKey : jobKeys) {
  207. List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);
  208. for (Trigger trigger : triggers) {
  209. JobDetails jobDetails = new JobDetails();
  210. if (trigger instanceof CronTrigger) {
  211. CronTrigger cronTrigger = (CronTrigger) trigger;
  212. jobDetails.setCronExpression(cronTrigger.getCronExpression());
  213. jobDetails.setTimeZone(cronTrigger.getTimeZone().getDisplayName());
  214. }
  215. jobDetails.setTriggerGroupName(trigger.getKey().getName());
  216. jobDetails.setTriggerName(trigger.getKey().getGroup());
  217. jobDetails.setJobGroupName(jobKey.getGroup());
  218. jobDetails.setJobName(jobKey.getName());
  219. jobDetails.setStartTime(trigger.getStartTime());
  220. jobDetails.setJobClassName(sched.getJobDetail(jobKey).getJobClass().getName());
  221. jobDetails.setNextFireTime(trigger.getNextFireTime());
  222. jobDetails.setPreviousFireTime(trigger.getPreviousFireTime());
  223. jobDetails.setStatus(sched.getTriggerState(trigger.getKey()).name());
  224. jobList.add(jobDetails);
  225. }
  226. }
  227. } catch (SchedulerException e) {
  228. e.printStackTrace();
  229. }
  230. return new PageInfo<>(jobList);
  231. }
  232.  
  233. /**
  234. * 获取所有计划中的任务列表
  235. *
  236. * @return
  237. */
  238. public List<Map<String, Object>> queryAllJob() {
  239. List<Map<String, Object>> jobList = null;
  240. try {
  241. GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
  242. Set<JobKey> jobKeys = sched.getJobKeys(matcher);
  243. jobList = new ArrayList<>();
  244. for (JobKey jobKey : jobKeys) {
  245. List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);
  246. for (Trigger trigger : triggers) {
  247. Map<String, Object> map = new HashMap<>();
  248. map.put("jobName", jobKey.getName());
  249. map.put("jobGroupName", jobKey.getGroup());
  250. map.put("description", "trigger:" + trigger.getKey());
  251. Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());
  252. map.put("jobStatus", triggerState.name());
  253. if (trigger instanceof CronTrigger) {
  254. CronTrigger cronTrigger = (CronTrigger) trigger;
  255. String cronExpression = cronTrigger.getCronExpression();
  256. map.put("jobTime", cronExpression);
  257. }
  258. jobList.add(map);
  259. }
  260. }
  261. } catch (SchedulerException e) {
  262. e.printStackTrace();
  263. }
  264. return jobList;
  265. }
  266.  
  267. /**
  268. * 获取所有正在运行的job
  269. *
  270. * @return
  271. */
  272. public List<Map<String, Object>> queryRunJon() {
  273. List<Map<String, Object>> jobList = null;
  274. try {
  275. List<JobExecutionContext> executingJobs = sched.getCurrentlyExecutingJobs();
  276. jobList = new ArrayList<>(executingJobs.size());
  277. for (JobExecutionContext executingJob : executingJobs) {
  278. Map<String, Object> map = new HashMap<>();
  279. JobDetail jobDetail = executingJob.getJobDetail();
  280. JobKey jobKey = jobDetail.getKey();
  281. Trigger trigger = executingJob.getTrigger();
  282. map.put("jobName", jobKey.getName());
  283. map.put("jobGroupName", jobKey.getGroup());
  284. map.put("description", "trigger:" + trigger.getKey());
  285. Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());
  286. map.put("jobStatus", triggerState.name());
  287. if (trigger instanceof CronTrigger) {
  288. CronTrigger cronTrigger = (CronTrigger) trigger;
  289. String cronExpression = cronTrigger.getCronExpression();
  290. map.put("jobTime", cronExpression);
  291. }
  292. jobList.add(map);
  293. }
  294. } catch (SchedulerException e) {
  295. e.printStackTrace();
  296. }
  297. return jobList;
  298. }
  299. }

Job控制器接口

  1. package tech.pdai.springboot.quartz.cluster.controller;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. import com.github.pagehelper.PageInfo;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.scheduling.quartz.QuartzJobBean;
  9. import org.springframework.web.bind.annotation.GetMapping;
  10. import org.springframework.web.bind.annotation.PostMapping;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RequestParam;
  13. import org.springframework.web.bind.annotation.RestController;
  14. import tech.pdai.springboot.quartz.cluster.entity.JobDetails;
  15. import tech.pdai.springboot.quartz.cluster.manager.QuartzManager;
  16.  
  17.  
  18. /**
  19. * @author pdai
  20. */
  21. @RestController
  22. @RequestMapping(value = "/job")
  23. public class JobController {
  24.  
  25. @Autowired
  26. private QuartzManager qtzManager;
  27.  
  28. @SuppressWarnings("unchecked")
  29. private static Class<? extends QuartzJobBean> getClass(String classname) throws Exception {
  30. Class<?> class1 = Class.forName(classname);
  31. return (Class<? extends QuartzJobBean>) class1;
  32. }
  33.  
  34. /**
  35. * @param jobClassName
  36. * @param jobGroupName
  37. * @param cronExpression
  38. * @throws Exception
  39. */
  40. @PostMapping(value = "/addjob")
  41. public void addjob(@RequestParam(value = "jobClassName") String jobClassName,
  42. @RequestParam(value = "jobGroupName") String jobGroupName,
  43. @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
  44. qtzManager.addOrUpdateJob(getClass(jobClassName), jobClassName, jobGroupName, cronExpression);
  45. }
  46.  
  47. /**
  48. * @param jobClassName
  49. * @param jobGroupName
  50. * @throws Exception
  51. */
  52. @PostMapping(value = "/pausejob")
  53. public void pausejob(@RequestParam(value = "jobClassName") String jobClassName,
  54. @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
  55. qtzManager.pauseJob(jobClassName, jobGroupName);
  56. }
  57.  
  58. /**
  59. * @param jobClassName
  60. * @param jobGroupName
  61. * @throws Exception
  62. */
  63. @PostMapping(value = "/resumejob")
  64. public void resumejob(@RequestParam(value = "jobClassName") String jobClassName,
  65. @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
  66. qtzManager.resumeJob(jobClassName, jobGroupName);
  67. }
  68.  
  69. /**
  70. * @param jobClassName
  71. * @param jobGroupName
  72. * @param cronExpression
  73. * @throws Exception
  74. */
  75. @PostMapping(value = "/reschedulejob")
  76. public void rescheduleJob(@RequestParam(value = "jobClassName") String jobClassName,
  77. @RequestParam(value = "jobGroupName") String jobGroupName,
  78. @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
  79. qtzManager.addOrUpdateJob(getClass(jobClassName), jobClassName, jobGroupName, cronExpression);
  80. }
  81.  
  82. /**
  83. * @param jobClassName
  84. * @param jobGroupName
  85. * @throws Exception
  86. */
  87. @PostMapping(value = "/deletejob")
  88. public void deletejob(@RequestParam(value = "jobClassName") String jobClassName,
  89. @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
  90. qtzManager.deleteJob(jobClassName, jobGroupName);
  91. }
  92.  
  93. /**
  94. * @param pageNum
  95. * @param pageSize
  96. * @return
  97. */
  98. @GetMapping(value = "/queryjob")
  99. public Map<String, Object> queryjob(@RequestParam(value = "pageNum") Integer pageNum,
  100. @RequestParam(value = "pageSize") Integer pageSize) {
  101. PageInfo<JobDetails> jobAndTrigger = qtzManager.queryAllJobBean(pageNum, pageSize);
  102. Map<String, Object> map = new HashMap<String, Object>();
  103. map.put("JobAndTrigger", jobAndTrigger);
  104. map.put("number", jobAndTrigger.getTotal());
  105. return map;
  106. }
  107. }

定义具体的Job

  1. package tech.pdai.springboot.quartz.cluster.job;
  2.  
  3. import java.util.Date;
  4.  
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.quartz.JobExecutionContext;
  7. import org.quartz.JobExecutionException;
  8. import org.springframework.scheduling.quartz.QuartzJobBean;
  9.  
  10. @Slf4j
  11. public class HelloJob extends QuartzJobBean {
  12.  
  13. @Override
  14. protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  15. // get parameters
  16. context.getJobDetail().getJobDataMap().forEach(
  17. (k, v) -> log.info("param, key:{}, value:{}", k, v)
  18. );
  19. // your logics
  20. log.info("Hello Job执行时间: " + new Date());
  21. }
  22. }

前端实现

简单用VueJS 写个页面测试

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>QuartzDemo</title>
  6. <link rel="stylesheet" href="https://unpkg.com/element-ui@2.0.5/lib/theme-chalk/index.css" rel="external nofollow" >
  7. <script src="https://unpkg.com/vue/dist/vue.js"></script>
  8. <script src="http://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.js"></script>
  9. <script src="https://unpkg.com/element-ui@2.0.5/lib/index.js"></script>
  10. <style>
  11. #top {
  12. background:#20A0FF;
  13. padding:5px;
  14. overflow:hidden
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="test">
  20.  
  21. <div id="top">
  22. <el-button type="text" @click="search" style="color:white">查询</el-button>
  23. <el-button type="text" @click="handleadd" style="color:white">添加</el-button>
  24. </span>
  25. </div>
  26. <br/>
  27.  
  28. <div style="margin-top:15px">
  29.  
  30. <el-table
  31. ref="testTable"
  32. :data="tableData"
  33. style="width:100%"
  34. border
  35. >
  36. <el-table-column
  37. prop="status"
  38. label="任务状态"
  39. sortable
  40. show-overflow-tooltip>
  41. </el-table-column>
  42. <el-table-column
  43. prop="jobName"
  44. label="任务名称"
  45. sortable
  46. show-overflow-tooltip>
  47. </el-table-column>
  48. <el-table-column
  49. prop="jobGroupName"
  50. label="任务所在组"
  51. sortable>
  52. </el-table-column>
  53. <el-table-column
  54. prop="jobClassName"
  55. label="任务类名"
  56. sortable>
  57. </el-table-column>
  58. <el-table-column
  59. prop="triggerName"
  60. label="触发器名称"
  61. sortable>
  62. </el-table-column>
  63. <el-table-column
  64. prop="triggerGroupName"
  65. label="触发器所在组"
  66. sortable>
  67. </el-table-column>
  68. <el-table-column
  69. prop="cronExpression"
  70. label="表达式"
  71. sortable>
  72. </el-table-column>
  73. <el-table-column
  74. prop="timeZone"
  75. label="时区"
  76. sortable>
  77. </el-table-column>
  78. <el-table-column label="操作" width="300">
  79. <template scope="scope">
  80. <el-button
  81. size="small"
  82. type="warning"
  83. @click="handlePause(scope.$index, scope.row)">暂停</el-button>
  84. <el-button
  85. size="small"
  86. type="info"
  87. @click="handleResume(scope.$index, scope.row)">恢复</el-button>
  88. <el-button
  89. size="small"
  90. type="danger"
  91. @click="handleDelete(scope.$index, scope.row)">删除</el-button>
  92. <el-button
  93. size="small"
  94. type="success"
  95. @click="handleUpdate(scope.$index, scope.row)">修改</el-button>
  96. </template>
  97. </el-table-column>
  98. </el-table>
  99. <div align="center">
  100. <el-pagination
  101. @size-change="handleSizeChange"
  102. @current-change="handleCurrentChange"
  103. :current-page="currentPage"
  104. :page-sizes="[10, 20, 30, 40]"
  105. :page-size="pagesize"
  106. layout="total, sizes, prev, pager, next, jumper"
  107. :total="totalCount">
  108. </el-pagination>
  109. </div>
  110. </div>
  111. <el-dialog title="添加任务" :visible.sync="dialogFormVisible">
  112. <el-form :model="form">
  113. <el-form-item label="任务名称" label-width="120px" style="width:35%">
  114. <el-input v-model="form.jobName" auto-complete="off"></el-input>
  115. </el-form-item>
  116. <el-form-item label="任务分组" label-width="120px" style="width:35%">
  117. <el-input v-model="form.jobGroup" auto-complete="off"></el-input>
  118. </el-form-item>
  119. <el-form-item label="表达式" label-width="120px" style="width:35%">
  120. <el-input v-model="form.cronExpression" auto-complete="off"></el-input>
  121. </el-form-item>
  122. </el-form>
  123. <div slot="footer" class="dialog-footer">
  124. <el-button @click="dialogFormVisible = false">取 消</el-button>
  125. <el-button type="primary" @click="add">确 定</el-button>
  126. </div>
  127. </el-dialog>
  128. <el-dialog title="修改任务" :visible.sync="updateFormVisible">
  129. <el-form :model="updateform">
  130. <el-form-item label="表达式" label-width="120px" style="width:35%">
  131. <el-input v-model="updateform.cronExpression" auto-complete="off"></el-input>
  132. </el-form-item>
  133. </el-form>
  134. <div slot="footer" class="dialog-footer">
  135. <el-button @click="updateFormVisible = false">取 消</el-button>
  136. <el-button type="primary" @click="update">确 定</el-button>
  137. </div>
  138. </el-dialog>
  139. </div>
  140. <footer align="center">
  141. <p>&copy; Quartz 任务管理</p>
  142. </footer>
  143.  
  144. <script>
  145. var vue = new Vue({
  146. el:"#test",
  147. data: {
  148. //表格当前页数据
  149. tableData: [],
  150. //请求的URL
  151. url:'job/queryjob',
  152. //默认每页数据量
  153. pagesize: 10,
  154. //当前页码
  155. currentPage: 1,
  156. //查询的页码
  157. start: 1,
  158. //默认数据总数
  159. totalCount: 1000,
  160. //添加对话框默认可见性
  161. dialogFormVisible: false,
  162. //修改对话框默认可见性
  163. updateFormVisible: false,
  164. //提交的表单
  165. form: {
  166. jobName: '',
  167. jobGroup: '',
  168. cronExpression: '',
  169. },
  170. updateform: {
  171. jobName: '',
  172. jobGroup: '',
  173. cronExpression: '',
  174. },
  175. },
  176.  
  177. methods: {
  178. //从服务器读取数据
  179. loadData: function(pageNum, pageSize){
  180. this.$http.get('job/queryjob?' + 'pageNum=' + pageNum + '&pageSize=' + pageSize).then(function(res){
  181. console.log(res)
  182. this.tableData = res.body.JobAndTrigger.list;
  183. this.totalCount = res.body.number;
  184. },function(){
  185. console.log('failed');
  186. });
  187. },
  188. //单行删除
  189. handleDelete: function(index, row) {
  190. this.$http.post('job/deletejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroupName},{emulateJSON: true}).then(function(res){
  191. this.loadData( this.currentPage, this.pagesize);
  192. },function(){
  193. console.log('failed');
  194. });
  195. },
  196. //暂停任务
  197. handlePause: function(index, row){
  198. this.$http.post('job/pausejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroupName},{emulateJSON: true}).then(function(res){
  199. this.loadData( this.currentPage, this.pagesize);
  200. },function(){
  201. console.log('failed');
  202. });
  203. },
  204. //恢复任务
  205. handleResume: function(index, row){
  206. this.$http.post('job/resumejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroupName},{emulateJSON: true}).then(function(res){
  207. this.loadData( this.currentPage, this.pagesize);
  208. },function(){
  209. console.log('failed');
  210. });
  211. },
  212. //搜索
  213. search: function(){
  214. this.loadData(this.currentPage, this.pagesize);
  215. },
  216. //弹出对话框
  217. handleadd: function(){
  218. this.dialogFormVisible = true;
  219. },
  220. //添加
  221. add: function(){
  222. this.$http.post('job/addjob',{"jobClassName":this.form.jobName,"jobGroupName":this.form.jobGroup,"cronExpression":this.form.cronExpression},{emulateJSON: true}).then(function(res){
  223. this.loadData(this.currentPage, this.pagesize);
  224. this.dialogFormVisible = false;
  225. },function(){
  226. console.log('failed');
  227. });
  228. },
  229. //更新
  230. handleUpdate: function(index, row){
  231. console.log(row)
  232. this.updateFormVisible = true;
  233. this.updateform.jobName = row.jobClassName;
  234. this.updateform.jobGroup = row.jobGroupName;
  235. },
  236. //更新任务
  237. update: function(){
  238. this.$http.post
  239. ('job/reschedulejob',
  240. {"jobClassName":this.updateform.jobName,
  241. "jobGroupName":this.updateform.jobGroup,
  242. "cronExpression":this.updateform.cronExpression
  243. },{emulateJSON: true}
  244. ).then(function(res){
  245. this.loadData(this.currentPage, this.pagesize);
  246. this.updateFormVisible = false;
  247. },function(){
  248. console.log('failed');
  249. });
  250. },
  251. //每页显示数据量变更
  252. handleSizeChange: function(val) {
  253. this.pagesize = val;
  254. this.loadData(this.currentPage, this.pagesize);
  255. },
  256. //页码变更
  257. handleCurrentChange: function(val) {
  258. this.currentPage = val;
  259. this.loadData(this.currentPage, this.pagesize);
  260. },
  261. },
  262. });
  263. //载入数据
  264. vue.loadData(vue.currentPage, vue.pagesize);
  265. </script>
  266. </body>
  267. </html>

测试效果

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

展示正在运行的Jobs:

增加新的Job:

Jobs持久化在数据库:

以上就是SpringBoot集成quartz实现定时任务详解的详细内容,更多关于SpringBoot quartz定时任务的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号