轉自我的個人博客: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,很容易就實現可視化的定時任務增刪改查操作。