SpringBoot 集成 Quartz + MySQL

Myth丶恋晨 2024-03-23 13:51 153阅读 0赞

工作原理解读

只要配置好 DataSource Quartz 会自动进行表的数据操作,

添加 Quartz Job 任务

保存 QRTZ_JOB_DETAILS、QRTZ_TRIGGERS => QRTZ_CRON_TRIGGERS

  1. public void addJob(QuartzJob job) throws SchedulerException {
  2. ....
  3. JobDetail jobDetail = JobBuilder.newJob(jobClass)
  4. .withIdentity(jobKey)
  5. .build();
  6. // 放入参数,运行时的方法可以获取
  7. jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
  8. //该行代码执行后,会将定时任务插入 QRTZ_JOB_DETAILS 等相关表
  9. scheduler.scheduleJob(jobDetail, trigger);
  10. ....
  11. }
  12. //org.quartz.impl.jdbcjobstore.JobStoreSupport
  13. public void storeJobAndTrigger(final JobDetail newJob, final OperableTrigger newTrigger) throws JobPersistenceException {
  14. this.executeInLock(this.isLockOnInsert() ? "TRIGGER_ACCESS" : null, new JobStoreSupport.VoidTransactionCallback() {
  15. public void executeVoid(Connection conn) throws JobPersistenceException {
  16. JobStoreSupport.this.storeJob(conn, newJob, false); //数据保存 QRTZ_JOB_DETAILS 表
  17. JobStoreSupport.this.storeTrigger(conn, newTrigger, newJob, false, "WAITING", false, false); //数据保存 QRTZ_TRIGGERS 表
  18. }
  19. });
  20. }
  21. public int insertTrigger(...){
  22. INSERT_TRIGGER
  23. insertExtendedTriggerProperties => INSERT_CRON_TRIGGER OR INSERT_BLOB_TRIGGER
  24. }

详见:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
将 job.getJobDataMap(),对像序列化后,存入 JOB_DETAILS.JOB_DATA字段,可以是一个对像,以执行定时任务时,会把该字段反序列化,根据前期设定的内容进行业务处理

68a667181b5056f4d63d35220c2270a1.png

获取 Quartz Job 任务

执行计划任务时,获取 Job Detail

  1. QuartzSchedulerThread.run()
  2. => qsRsrcs.getJobStore().acquireNextTriggers()
  3. => txCallback.execute(conn)
  4. => JobStoreSupport.acquireNextTriggers()
  5. => JobStoreSupport.retrieveJob()
  6. => StdJDBCDelegate.selectJobDetail()

d172b3b702c956aef0596d775bb1dad5.png

删除 Quartz Job 任务

  1. /**
  2. * <p>
  3. * Delete the base trigger data for a trigger.
  4. * </p>
  5. *
  6. * @param conn
  7. * the DB Connection
  8. * @return the number of rows deleted
  9. */
  10. public int deleteTrigger(Connection conn, TriggerKey triggerKey) throws SQLException {
  11. PreparedStatement ps = null;
  12. deleteTriggerExtension(conn, triggerKey);
  13. try {
  14. ps = conn.prepareStatement(rtp(DELETE_TRIGGER));
  15. ps.setString(1, triggerKey.getName());
  16. ps.setString(2, triggerKey.getGroup());
  17. return ps.executeUpdate();
  18. } finally {
  19. closeStatement(ps);
  20. }
  21. }

清除数据

  1. /**
  2. * 清任务顺序
  3. */
  4. public void clearData(Connection conn)
  5. throws SQLException {
  6. PreparedStatement ps = null;
  7. try {
  8. ps = conn.prepareStatement(rtp(DELETE_ALL_SIMPLE_TRIGGERS));
  9. ps.executeUpdate();
  10. ps.close();
  11. ps = conn.prepareStatement(rtp(DELETE_ALL_SIMPROP_TRIGGERS));
  12. ps.executeUpdate();
  13. ps.close();
  14. ps = conn.prepareStatement(rtp(DELETE_ALL_CRON_TRIGGERS));
  15. ps.executeUpdate();
  16. ps.close();
  17. ps = conn.prepareStatement(rtp(DELETE_ALL_BLOB_TRIGGERS));
  18. ps.executeUpdate();
  19. ps.close();
  20. ps = conn.prepareStatement(rtp(DELETE_ALL_TRIGGERS));
  21. ps.executeUpdate();
  22. ps.close();
  23. ps = conn.prepareStatement(rtp(DELETE_ALL_JOB_DETAILS));
  24. ps.executeUpdate();
  25. ps.close();
  26. ps = conn.prepareStatement(rtp(DELETE_ALL_CALENDARS));
  27. ps.executeUpdate();
  28. ps.close();
  29. ps = conn.prepareStatement(rtp(DELETE_ALL_PAUSED_TRIGGER_GRPS));
  30. ps.executeUpdate();
  31. } finally {
  32. closeStatement(ps);
  33. }
  34. }

Demo 代码

MySQL 脚本

quartz/tables_mysql.sql at v2.3.2 · quartz-scheduler/quartz · GitHub

清除数据

  1. DELETE FROM qrtz_simple_triggers ;
  2. DELETE FROM qrtz_simprop_triggers ;
  3. DELETE FROM qrtz_cron_triggers ;
  4. DELETE FROM qrtz_blob_triggers ;
  5. DELETE FROM qrtz_triggers ;
  6. DELETE FROM qrtz_job_details ;
  7. DELETE FROM qrtz_calendars ;
  8. DELETE FROM qrtz_paused_trigger_grps ;
  9. DELETE FROM qrtz_scheduler_state ;
  10. DELETE FROM qrtz_locks ;
  11. DELETE FROM qrtz_fired_triggers

Pom.xml
如果SpringBoot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-quartz</artifactId>
  4. </dependency>
  5. <!--Quartz 集成需要和数据库交互-->
  6. <dependency>
  7. <groupId>mysql</groupId>
  8. <artifactId>mysql-connector-java</artifactId>
  9. <version>5.0.8</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.alibaba</groupId>
  13. <artifactId>druid</artifactId>
  14. <version>1.1.20</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.mybatis.spring.boot</groupId>
  18. <artifactId>mybatis-spring-boot-starter</artifactId>
  19. </dependency>
  20. <!--hutool 工具类-->
  21. <dependency>
  22. <groupId>cn.hutool</groupId>
  23. <artifactId>hutool-all</artifactId>
  24. <version>5.3.7</version>
  25. </dependency>

946a887ecd0cacd535ccf5853e27c29f.png

QuartzJob 参考上图,建立实体

点击查看代码

核心代码:QuartzJobServiceImpl

点击查看代码

ScheduleConfig

点击查看代码

暂停后,qrtz_triggers 表的 TRIGGER_STATE = PAUSED

1d400cf2dbc02e37671c5b1a3541f5e0.png

运行效果
http://localhost:8088/schedule/add
http://localhost:8088/schedule/pause
http://localhost:8088/schedule/restart

  1. {"jobName":"测试","jobGroup":"DEFAULT","invokeTarget":"scheduletask.execute('VipSoft Quartz')","cronExpression":"0/10 * * * * ?","misfirePolicy":2,"concurrent":1,"status":"0"}

f01756b2bf0d7a022b46968813552d1f.png

参考

实现方式参考:若依(RuoYi),他是新建了一张中间表,通过 init() 方法,利用中心中间表进行定时任务的初始化

  1. /**
  2. * 项目启动时,初始化定时器
  3. 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
  4. */
  5. @PostConstruct
  6. public void init() throws SchedulerException, TaskException
  7. {
  8. scheduler.clear();
  9. List<SysJob> jobList = jobMapper.selectJobAll();
  10. for (SysJob job : jobList)
  11. {
  12. ScheduleUtils.createScheduleJob(scheduler, job);
  13. }
  14. }

发表评论

表情:
评论列表 (有 0 条评论,153人围观)

还没有评论,来说两句吧...

相关阅读