转自我的个人博客:Springboot集成quartz定时任务可视化配置
使用quartz定时任务已经有一段时间了,今天记录一下Springboot 2.x集成Quartz。
1、引入quartz jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、加入quartz配置
spring:
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
#初始化表结构
#jdbc:
#initialize-schema: never
我这里的jobstore使用的是jdbc jobstore,所有的定时任务都持久化于数据库中。
3、将存储quartz的表导入数据库
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
CREATE TABLE `qrtz_blob_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
`BLOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_calendars`;
CREATE TABLE `qrtz_calendars` (
`SCHED_NAME` varchar(120) NOT NULL,
`CALENDAR_NAME` varchar(190) NOT NULL,
`CALENDAR` blob NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
CREATE TABLE `qrtz_cron_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
`CRON_EXPRESSION` varchar(120) NOT NULL,
`TIME_ZONE_ID` varchar(80) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
CREATE TABLE `qrtz_fired_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`ENTRY_ID` varchar(95) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
`INSTANCE_NAME` varchar(190) NOT NULL,
`FIRED_TIME` bigint(13) NOT NULL,
`SCHED_TIME` bigint(13) NOT NULL,
`PRIORITY` int(11) NOT NULL,
`STATE` varchar(16) NOT NULL,
`JOB_NAME` varchar(190) DEFAULT NULL,
`JOB_GROUP` varchar(190) DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_job_details`;
CREATE TABLE `qrtz_job_details` (
`SCHED_NAME` varchar(120) NOT NULL,
`JOB_NAME` varchar(190) NOT NULL,
`JOB_GROUP` varchar(190) NOT NULL,
`DESCRIPTION` varchar(250) DEFAULT 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,
PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
`SCHED_NAME` varchar(120) NOT NULL,
`LOCK_NAME` varchar(40) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
CREATE TABLE `qrtz_scheduler_state` (
`SCHED_NAME` varchar(120) NOT NULL,
`INSTANCE_NAME` varchar(190) NOT NULL,
`LAST_CHECKIN_TIME` bigint(13) NOT NULL,
`CHECKIN_INTERVAL` bigint(13) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
CREATE TABLE `qrtz_simple_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) 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`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
CREATE TABLE `qrtz_simprop_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
`STR_PROP_1` varchar(512) DEFAULT NULL,
`STR_PROP_2` varchar(512) DEFAULT NULL,
`STR_PROP_3` varchar(512) DEFAULT NULL,
`INT_PROP_1` int(11) DEFAULT NULL,
`INT_PROP_2` int(11) DEFAULT NULL,
`LONG_PROP_1` bigint(20) DEFAULT NULL,
`LONG_PROP_2` bigint(20) DEFAULT NULL,
`DEC_PROP_1` decimal(13,4) DEFAULT NULL,
`DEC_PROP_2` decimal(13,4) DEFAULT NULL,
`BOOL_PROP_1` varchar(1) DEFAULT NULL,
`BOOL_PROP_2` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `qrtz_triggers`;
CREATE TABLE `qrtz_triggers` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(190) NOT NULL,
`TRIGGER_GROUP` varchar(190) NOT NULL,
`JOB_NAME` varchar(190) NOT NULL,
`JOB_GROUP` varchar(190) NOT NULL,
`DESCRIPTION` varchar(250) DEFAULT NULL,
`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
`PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
`PRIORITY` int(11) DEFAULT NULL,
`TRIGGER_STATE` varchar(16) NOT NULL,
`TRIGGER_TYPE` varchar(8) NOT NULL,
`START_TIME` bigint(13) NOT NULL,
`END_TIME` bigint(13) DEFAULT NULL,
`CALENDAR_NAME` varchar(190) DEFAULT NULL,
`MISFIRE_INSTR` smallint(2) DEFAULT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ps:上面的表结构是我从数据库导出的,由于外键影响可能建表顺序需要调整。
4、springboot启动类上加上@EnableScheduling注解,就这样springboot已经自动帮我们生成好了任务调度器。
5、封装QuartzJobService
QuartzJobService接口
public interface QuartzJobService {
/**
* 创建job
*
* @param jobDto 任务类
*/
void addJob(JobDto jobDto)throws Exception;
/**
* 创建job,可传参
*
* @param jobDto 任务类
* @param argMap map形式参数
*/
void addJob(JobDto jobDto, Map<String, Object> argMap)throws Exception;
/**
* 暂停job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
void pauseJob(String jobName, String jobGroupName)throws Exception;
/**
* 恢复job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
void resumeJob(String jobName, String jobGroupName)throws Exception;
/**
* job 更新,只更新频率
*
*/
void updateJob(JobDto jobDto)throws Exception;
/**
* job 更新,更新频率和参数
*
* @param argMap 参数
*/
void updateJob(JobDto jobDto, Map<String, Object> argMap)throws Exception;
/**
* job 更新,只更新更新参数
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param argMap 参数
*/
void updateJob(String jobName, String jobGroupName, Map<String, Object> argMap)throws Exception;
/**
* job 删除
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
void deleteJob(String jobName, String jobGroupName)throws Exception;
/**
* 启动所有定时任务
*/
void startAllJobs()throws Exception;
/**
* 关闭所有定时任务
*/
void shutdownAllJobs()throws Exception;
/**
* 获取所有任务列表
*
* @return
*/
List<JobDto> getAllJob()throws Exception;
/**
* 通过jobname查询job
* @param jobName
* @return job的状态
*/
Trigger.TriggerState getJobByName(String jobName)throws Exception;
}
QuartzJobService实现类
@Service
public class QuartzJobServiceImpl implements QuartzJobService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private Scheduler scheduler;
/**
* 创建job
*
*/
public void addJob(JobDto jobDto)throws Exception {
addJob(jobDto, null);
}
/**
* 创建job,可传参
*
* @param jobDto 任务类
* @param argMap map形式参数
*/
public void addJob(JobDto jobDto, Map<String, Object> argMap)throws Exception {
Class<?> clazz = jobDto.getClazz();
String jobName = jobDto.getJobName();
String groupName = jobDto.getGroupName();
String cronExpression = jobDto.getCronExpression();
// 启动调度器
scheduler.start();
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(((Job) clazz.newInstance()).getClass()).withIdentity(jobName, groupName).withDescription(jobDto.getDesc()).build();
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName).withSchedule(scheduleBuilder).build();
//获得JobDataMap,写入数据
if (argMap != null) {
trigger.getJobDataMap().putAll(argMap);
}
if (!StringUtils.isBlank(jobDto.getTime())){
trigger.getJobDataMap().put("time", jobDto.getTime());
}
scheduler.scheduleJob(jobDetail, trigger);
}
/**
* 暂停job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
public void pauseJob(String jobName, String jobGroupName)throws Exception {
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
}
/**
* 恢复job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
public void resumeJob(String jobName, String jobGroupName)throws Exception {
scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
}
/**
* job 更新,只更新频率
*
*/
public void updateJob(JobDto jobDto)throws Exception {
updateJob(jobDto, null);
}
/**
* job 更新,更新频率和参数
* @param argMap 参数
*/
public void updateJob(JobDto jobDto, Map<String, Object> argMap)throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobDto.getJobName(), jobDto.getGroupName());
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobDto.getCronExpression());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//修改map
if (argMap != null) {
trigger.getJobDataMap().putAll(argMap);
}
trigger.getJobDataMap().put("time", jobDto.getTime());
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
/**
* job 更新,只更新更新参数
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param argMap 参数
*/
public void updateJob(String jobName, String jobGroupName, Map<String, Object> argMap)throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
//修改map
trigger.getJobDataMap().putAll(argMap);
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
/**
* job 删除
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
*/
public void deleteJob(String jobName, String jobGroupName)throws Exception {
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
}
/**
* 启动所有定时任务
*/
public void startAllJobs()throws Exception {
scheduler.start();
}
/**
* 关闭所有定时任务
*/
public void shutdownAllJobs()throws Exception {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
}
/**
* 获取所有任务列表
*
* @return
*/
public List<JobDto> getAllJob()throws Exception {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
List<JobDto> jobList = new ArrayList<>();
Set<JobKey> jobKeys = null;
jobKeys = scheduler.getJobKeys(matcher);
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
JobDto jobDto = new JobDto();
jobDto.setJobName(jobKey.getName());
jobDto.setGroupName(jobKey.getGroup());
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
jobDto.setClassName(jobDetail.getJobClass().getName());
jobDto.setClazz(jobDetail.getJobClass());
jobDto.setTriggerName(trigger.getCalendarName());
jobDto.setDesc(jobDetail.getDescription());
jobDto.setTime(trigger.getJobDataMap().getString("time"));
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
jobDto.setStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
jobDto.setCronExpression(cronExpression);
}
jobList.add(jobDto);
}
}
return jobList;
}
/**
* 通过jobname查询job
* @param jobName
* @return job的状态
*/
public Trigger.TriggerState getJobByName(String jobName)throws Exception {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = null;
jobKeys = scheduler.getJobKeys(matcher);
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
if (jobKey.getName().equals(jobName)){
return triggerState;
}
}
}
return null;
}
}
至此,springboot已经集成好了quartz,通过我们封装的QuartzJobService,很容易就实现可视化的定时任务增删改查操作。