Quartz 介绍
Quartz 定时任务可分为Trigger(触发器)、Job(任务)和Scheduler(调度器),定时任务的逻辑大体为:创建触发器和任务,并将其加入到调度器中,如下图所示:
Trigger 有五种触发器:
SimpleTrigger 触发器:需要在特定的日期/时间启动,且以指定的间隔时间(单位毫秒)重复执行 n 次任务,如 :在 9:00 开始,每隔1小时,每隔几分钟,每隔几秒钟执行一次 。没办法指定每隔一个月执行一次(每月的时间间隔不是固定值)。
CalendarIntervalTrigger 触发器:指定从某一个时间开始,以一定的时间间隔(单位有秒,分钟,小时,天,月,年,星期)执行的任务。
DailyTimeIntervalTrigger 触发器:指定每天的某个时间段内,以一定的时间间隔执行任务。并且支持指定星期。如:指定每天 9:00 至 18:00 ,每隔 70 秒执行一次,并且只要周一至周五执行。
CronTrigger 触发器:基于日历的任务调度器,即指定星期、日期的某时间执行任务。
NthIncludedDayTrigger 触发器:不同时间间隔的第 n 天执行任务。比如,在每个月的第 15 日处理财务发票记帐,同样设定双休日或者假期。
引入quartz依赖
<!--定时器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
TaskScheduler类:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class TaskScheduler {
private String jobName;
private String jobGroupName;
private String state;
private String jobClass;
private String intervalUnit;
private String intervalUnitName;
private Integer timeInterval;
private String cronExpression;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date startTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date endTime;
private String description;
}
JobQuery类(查询用):
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class JobQuery {
@ApiModelProperty(value = "模糊查询任务描述")
private String jobNameLike;
}
TaskSchedulerController类:
import com.example.demo.system.domain.Result;
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import com.example.demo.system.service.ITaskSchedulerService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@Api(value = "system/taskScheduler", tags = "定时任务")
@RequestMapping("taskScheduler")
public class TaskSchedulerController {
@Resource
private ITaskSchedulerService schedulerService;
/**
* 添加定时任务信息
*
* @param taskScheduler 定时任务信息
* @return ReturnModel 添加定时任务
*/
@PostMapping(value = "save")
public Result<String> save(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName":"bookTask2",
// "description":"书籍定时任务",
// "jobTypeRadio":"expression",
// "startTime":"2024-01-12 15:20:00",
// "endTime":"2024-01-13 00:00:00",
// "jobClass":"com.example.demo.system.controller.BookTask",
// "cronExpression":"*/30 * * * * ?"
// }
schedulerService.save(taskScheduler);
return Result.success(taskScheduler.getJobName());
}
/**
* 移除定时任务
*
* @param taskScheduler 定时任务信息
* @return ReturnModel 移除定时任务
*/
@PostMapping(value = "/delete")
public Result<String> delete(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName": "bookTask"
// }
schedulerService.delete(taskScheduler.getJobName());
return Result.success(taskScheduler.getJobName());
}
/**
* 修改定时任务
*
* @param taskScheduler 定时任务信息
* @return ReturnModel 修改定时任务
*/
@PostMapping(value = "update")
public Result<String> update(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName":"bookTask",
// "description":"1",
// "jobTypeRadio":"expression",
// "startTime":"2024-01-13 14:00:00",
// "endTime":"",
// "jobClass":"com.example.demo.system.controller.BookTask",
// "cronExpression":"*/30 * * * * ?"
// }
schedulerService.update(taskScheduler);
return Result.success(taskScheduler.getJobName());
}
/**
* 暂停定时任务
*
* @param taskScheduler 定时任务名称
* @return ReturnModel 暂停定时任务
*/
@PostMapping(value = "pause")
public Result<String> pause(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName": "bookTask2"
// }
schedulerService.pause(taskScheduler.getJobName());
return Result.success(taskScheduler.getJobName());
}
/**
* 恢复定时任务
*
* @param taskScheduler 定时任务名称
* @return ReturnModel 恢复定时任务
*/
@PostMapping(value = "resume")
public Result<String> resume(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName": "bookTask2"
// }
schedulerService.resume(taskScheduler.getJobName());
return Result.success(taskScheduler.getJobName());
}
/**
* 执行定时任务
*
* @param taskScheduler 定时任务名称
* @return ReturnModel 执行定时任务
*/
@PostMapping(value = "executeJob")
public Result<String> executeJob(@RequestBody TaskScheduler taskScheduler) {
// {
// "jobName": "bookTask2"
// }
schedulerService.executeJob(taskScheduler.getJobName());
return Result.success(taskScheduler.getJobName());
}
/**
* 查询单个定时任务信息
*
* @param jobName 任务名称
* @return ReturnModel 查询单个定时任务信息
*/
@GetMapping(value = "selectByName")
public Result<TaskScheduler> selectByName(@RequestParam("jobName") String jobName) {
TaskScheduler taskScheduler = schedulerService.selectByName(jobName);
return Result.success(taskScheduler);
}
/**
* 查询定时任务列表
*
* @param jobQuery 查询条件
* @return ReturnModel 查询定时任务列表
*/
@PostMapping(value = "selectList")
public Result<List<TaskScheduler>> selectList(@RequestBody JobQuery jobQuery) {
// {
// "jobNameLike": ""
// }
List<TaskScheduler> taskSchedulers = schedulerService.selectList(jobQuery);
return Result.success(taskSchedulers);
}
}
ITaskSchedulerService接口:
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import java.util.List;
public interface ITaskSchedulerService {
/**
* 添加定时任务信息
*
* @param taskScheduler 定时任务信息
*/
void save(TaskScheduler taskScheduler);
/**
* 移除定时任务--根据任务名称移除
*
* @param jobName 任务名
*/
void delete(String jobName);
/**
* 移除定时任务
*
* @param groupName 组名
* @param jobName 任务名
*/
void delete(String jobName, String groupName);
/**
* 修改定时任务
*
* @param taskScheduler 任务信息
*/
void update(TaskScheduler taskScheduler);
/**
* 添加任务
*
* @param jobName 任务名
* @return 任务信息
*/
TaskScheduler selectByName(String jobName);
/**
* 查询单个定时任务信息
*
* @param groupName 组名称
* @param jobName 任务名称
* @return 查询结果
*/
TaskScheduler selectByName(String jobName, String groupName);
/**
* 查询定时任务列表
*
* @param jobQuery 查询条件
* @return 查询结果
*/
List<TaskScheduler> selectList(JobQuery jobQuery);
/**
* 暂停定时任务
*
* @param jobName 任务名
*/
void pause(String jobName);
/**
* 暂停定时任务
*
* @param jobName 任务名
* @param groupName 组名
*/
void pause(String jobName, String groupName);
/**
* 恢复定时任务
*
* @param jobName 任务名
*/
void resume(String jobName);
/**
* 恢复定时任务
*
* @param jobName 任务名
* @param groupName 组名
*/
void resume(String jobName, String groupName);
/**
* 执行定时任务
*
* @param jobName 任务名
*/
void executeJob(String jobName);
/**
* 执行定时任务
*
* @param jobName 任务名
* @param groupName 组名
*/
void executeJob(String jobName, String groupName);
}
TaskSchedulerServiceImpl实现类:
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import com.example.demo.system.service.ITaskSchedulerService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CalendarIntervalTriggerImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Service
@Slf4j
public class TaskSchedulerServiceImpl implements ITaskSchedulerService {
@Resource
private Scheduler scheduler;
@Override
@SneakyThrows
public void save(TaskScheduler taskScheduler) {
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(taskScheduler.getJobClass());
String jobName = taskScheduler.getJobName();
String jobGroupName = StrUtil.isEmpty(taskScheduler.getJobGroupName()) ? Scheduler.DEFAULT_GROUP : taskScheduler.getJobGroupName();
String triggerGroupName = StrUtil.isEmpty(taskScheduler.getJobGroupName()) ? Scheduler.DEFAULT_GROUP : taskScheduler.getJobGroupName();
Date startTime = taskScheduler.getStartTime() == null ? new Date() : taskScheduler.getStartTime();
Date endTime = taskScheduler.getEndTime();
String description = StrUtil.isEmpty(taskScheduler.getDescription()) ? "" : taskScheduler.getDescription();
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).withDescription(description).build();
if (taskScheduler.getCronExpression() != null && taskScheduler.getCronExpression().length() > 0) {
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName, triggerGroupName)
.startAt(startTime)
.endAt(endTime)
.withSchedule(CronScheduleBuilder.cronSchedule(taskScheduler.getCronExpression()).withMisfireHandlingInstructionDoNothing())
.build();
scheduler.scheduleJob(jobDetail, trigger);
} else {
DateBuilder.IntervalUnit cycleUnit = DateBuilder.IntervalUnit.valueOf(taskScheduler.getIntervalUnit());
Integer timeInterval = taskScheduler.getTimeInterval();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName, triggerGroupName)
.startAt(startTime)
.endAt(endTime)
.withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withInterval(timeInterval, cycleUnit).withMisfireHandlingInstructionDoNothing())
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
}
/**
* 移除定时任务--根据任务名称移除
*/
@Override
public void delete(String jobName) {
delete(jobName, Scheduler.DEFAULT_GROUP);
}
/**
* 移除定时任务
*/
@Override
@SneakyThrows
public void delete(String jobName, String groupName) {
groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
JobKey jobKey = new JobKey(jobName, groupName);
TriggerKey triggerKey = new TriggerKey(jobName, groupName);
scheduler.pauseTrigger(triggerKey);
scheduler.pauseJob(jobKey);
// 移除触发器
scheduler.unscheduleJob(triggerKey);
// 删除任务
scheduler.deleteJob(jobKey);
}
/**
* 修改定时任务
*/
@Override
@SneakyThrows
public void update(TaskScheduler taskScheduler) {
delete(taskScheduler.getJobName());
save(taskScheduler);
}
/**
* 查询单个定时任务
*/
@Override
@SneakyThrows
public TaskScheduler selectByName(String jobName, String groupName) {
groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
TaskScheduler taskScheduler = new TaskScheduler();
JobKey jobKey = new JobKey(jobName, groupName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
taskScheduler.setJobName(jobName);
taskScheduler.setJobGroupName(groupName);
setJob(jobKey, taskScheduler, jobDetail);
return taskScheduler;
}
/**
* 查询单个定时任务
*/
@Override
public TaskScheduler selectByName(String jobName) {
return selectByName(jobName, Scheduler.DEFAULT_GROUP);
}
/**
* 查询定时任务列表
*/
@Override
@SneakyThrows
public List<TaskScheduler> selectList(JobQuery jobQuery) {
List<TaskScheduler> taskSchedulers = new ArrayList<>();
GroupMatcher<JobKey> mathcher = GroupMatcher.anyJobGroup();
String keyWord = jobQuery.getJobNameLike();
Set<JobKey> jobKeys = scheduler.getJobKeys(mathcher);
if (CollUtil.isEmpty(jobKeys)) {
return new ArrayList<>();
}
for (JobKey jobKey : jobKeys) {
if (StrUtil.isNotEmpty(keyWord) && !jobKey.getName().contains(keyWord)) {
continue;
}
TaskScheduler taskScheduler = new TaskScheduler();
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
taskScheduler.setJobName(jobKey.getName());
taskScheduler.setJobGroupName(jobKey.getGroup());
List<? extends Trigger> triggers = setJob(jobKey, taskScheduler, jobDetail);
taskScheduler.setState(scheduler.getTriggerState(triggers.get(0).getKey()).name());
taskSchedulers.add(taskScheduler);
}
return taskSchedulers;
}
private List<? extends Trigger> setJob(JobKey jobKey, TaskScheduler taskScheduler, JobDetail jobDetail) throws SchedulerException {
taskScheduler.setJobClass(jobDetail.getJobClass().getName());
taskScheduler.setDescription(jobDetail.getDescription());
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
Trigger trigger = triggers.get(0);
taskScheduler.setStartTime(trigger.getStartTime());
taskScheduler.setEndTime(trigger.getEndTime());
if (trigger.getClass().equals(CronTriggerImpl.class)) {
CronTriggerImpl cronTriggerImpl = (CronTriggerImpl) trigger;
taskScheduler.setCronExpression(cronTriggerImpl.getCronExpression());
}
if (trigger.getClass().equals(CalendarIntervalTriggerImpl.class)) {
CalendarIntervalTriggerImpl calendarIntervalTriggerImpl = (CalendarIntervalTriggerImpl) trigger;
taskScheduler.setIntervalUnit(calendarIntervalTriggerImpl.getRepeatIntervalUnit().toString());
taskScheduler.setTimeInterval(calendarIntervalTriggerImpl.getRepeatInterval());
}
return triggers;
}
/**
* 暂停定时任务
*/
@Override
public void pause(String jobName) {
pause(jobName, Scheduler.DEFAULT_GROUP);
}
/**
* 暂停定时任务
*/
@Override
@SneakyThrows
public void pause(String jobName, String groupName) {
groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
TriggerKey triggerKey = new TriggerKey(jobName, groupName);
scheduler.pauseTrigger(triggerKey);
JobKey jobKey = new JobKey(jobName);
scheduler.pauseJob(jobKey);
}
/**
* 恢复定时任务
*/
@Override
public void resume(String jobName) {
resume(jobName, Scheduler.DEFAULT_GROUP);
}
/**
* 恢复定时任务
*/
@Override
@SneakyThrows
public void resume(String jobName, String groupName) {
groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
TriggerKey triggerKey = new TriggerKey(jobName, groupName);
scheduler.resumeTrigger(triggerKey);
JobKey jobKey = new JobKey(jobName);
scheduler.resumeJob(jobKey);
}
/**
* 执行定时任务
*/
@Override
public void executeJob(String jobName) {
executeJob(jobName, Scheduler.DEFAULT_GROUP);
}
/**
* 执行定时任务
*/
@Override
@SneakyThrows
public void executeJob(String jobName, String groupName) {
groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
JobKey jobKey = new JobKey(jobName, groupName);
scheduler.triggerJob(jobKey);
}
}
定时任务业务逻辑类BookTask:
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Slf4j
public class BookTask extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
log.info("book定时任务-开始执行:{}", DateUtil.date().toString("yyyy-MM-dd HH:mm:ss"));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("book定时任务-执行结束:{}", DateUtil.date().toString("yyyy-MM-dd HH:mm:ss"));
}
}
以上动态配置定时任务需要的东西准备完毕,下一步就是配置
在此用swaggger来做测试
1、保存定时任务,我在此保存了两次 bookTask和bookTask2
注意:如果传了开始时间-startTime和结束时间-endTime,开始时间一定要小于结束时间,且开始时间要是一个未来时间,否则永远不会生效,也可以只传开始时间传结束时间。
2、看看列表
3、查看具体信息
4、更新定时任务:
5、删除定时任务
6、执行一次定时任务
7、暂停定时任务
8、恢复定时任务
9、持久化:在配置文件中加上该配置并新建数据表即可,重启项目后,配置的定时任务还在
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: embedded
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;
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 INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;
注意:如果有其他业务逻辑 ,需要在对应的方法里加业务代码