SpringBoot 集成 Quartz + MySQL
工作原理解读
只要配置好 DataSource Quartz 会自动进行表的数据操作,
添加 Quartz Job 任务
保存 QRTZ_JOB_DETAILS、QRTZ_TRIGGERS => QRTZ_CRON_TRIGGERS
public void addJob(QuartzJob job) throws SchedulerException {
....
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(jobKey)
.build();
// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
//该行代码执行后,会将定时任务插入 QRTZ_JOB_DETAILS 等相关表
scheduler.scheduleJob(jobDetail, trigger);
....
}
//org.quartz.impl.jdbcjobstore.JobStoreSupport
public void storeJobAndTrigger(final JobDetail newJob, final OperableTrigger newTrigger) throws JobPersistenceException {
this.executeInLock(this.isLockOnInsert() ? "TRIGGER_ACCESS" : null, new JobStoreSupport.VoidTransactionCallback() {
public void executeVoid(Connection conn) throws JobPersistenceException {
JobStoreSupport.this.storeJob(conn, newJob, false); //数据保存 QRTZ_JOB_DETAILS 表
JobStoreSupport.this.storeTrigger(conn, newTrigger, newJob, false, "WAITING", false, false); //数据保存 QRTZ_TRIGGERS 表
}
});
}
public int insertTrigger(...){
INSERT_TRIGGER
insertExtendedTriggerProperties => INSERT_CRON_TRIGGER OR INSERT_BLOB_TRIGGER
}
详见:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
将 job.getJobDataMap(),对像序列化后,存入 JOB_DETAILS.JOB_DATA
字段,可以是一个对像,以执行定时任务时,会把该字段反序列化,根据前期设定的内容进行业务处理
获取 Quartz Job 任务
执行计划任务时,获取 Job Detail
QuartzSchedulerThread.run()
=> qsRsrcs.getJobStore().acquireNextTriggers()
=> txCallback.execute(conn)
=> JobStoreSupport.acquireNextTriggers()
=> JobStoreSupport.retrieveJob()
=> StdJDBCDelegate.selectJobDetail()
删除 Quartz Job 任务
/**
* <p>
* Delete the base trigger data for a trigger.
* </p>
*
* @param conn
* the DB Connection
* @return the number of rows deleted
*/
public int deleteTrigger(Connection conn, TriggerKey triggerKey) throws SQLException {
PreparedStatement ps = null;
deleteTriggerExtension(conn, triggerKey);
try {
ps = conn.prepareStatement(rtp(DELETE_TRIGGER));
ps.setString(1, triggerKey.getName());
ps.setString(2, triggerKey.getGroup());
return ps.executeUpdate();
} finally {
closeStatement(ps);
}
}
清除数据
/**
* 清任务顺序
*/
public void clearData(Connection conn)
throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(rtp(DELETE_ALL_SIMPLE_TRIGGERS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_SIMPROP_TRIGGERS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_CRON_TRIGGERS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_BLOB_TRIGGERS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_TRIGGERS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_JOB_DETAILS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_CALENDARS));
ps.executeUpdate();
ps.close();
ps = conn.prepareStatement(rtp(DELETE_ALL_PAUSED_TRIGGER_GRPS));
ps.executeUpdate();
} finally {
closeStatement(ps);
}
}
Demo 代码
MySQL 脚本
quartz/tables_mysql.sql at v2.3.2 · quartz-scheduler/quartz · GitHub
清除数据
DELETE FROM qrtz_simple_triggers ;
DELETE FROM qrtz_simprop_triggers ;
DELETE FROM qrtz_cron_triggers ;
DELETE FROM qrtz_blob_triggers ;
DELETE FROM qrtz_triggers ;
DELETE FROM qrtz_job_details ;
DELETE FROM qrtz_calendars ;
DELETE FROM qrtz_paused_trigger_grps ;
DELETE FROM qrtz_scheduler_state ;
DELETE FROM qrtz_locks ;
DELETE FROM qrtz_fired_triggers
Pom.xml
如果SpringBoot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--Quartz 集成需要和数据库交互-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--hutool 工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
QuartzJob 参考上图,建立实体
点击查看代码
核心代码:QuartzJobServiceImpl
点击查看代码
ScheduleConfig
点击查看代码
暂停后,qrtz_triggers 表的 TRIGGER_STATE = PAUSED
运行效果http://localhost:8088/schedule/add
http://localhost:8088/schedule/pause
http://localhost:8088/schedule/restart
{"jobName":"测试","jobGroup":"DEFAULT","invokeTarget":"scheduletask.execute('VipSoft Quartz')","cronExpression":"0/10 * * * * ?","misfirePolicy":2,"concurrent":1,"status":"0"}
参考
实现方式参考:若依(RuoYi),他是新建了一张中间表,通过 init() 方法,利用中心中间表进行定时任务的初始化
/**
* 项目启动时,初始化定时器
主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
*/
@PostConstruct
public void init() throws SchedulerException, TaskException
{
scheduler.clear();
List<SysJob> jobList = jobMapper.selectJobAll();
for (SysJob job : jobList)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
}
还没有评论,来说两句吧...