Springboot2.x+Quartz分布式集群的實現(xiàn)
生產(chǎn)環(huán)境一般都是多節(jié)點高可用,Springboot本身自帶有定時任務(wù)功能,但我們項目需求要求能對定時任務(wù)進行增,刪,改,查。所以考慮引進Quartz,引入Quartz就需要考慮分布式集群,所以就有了這篇文章。
數(shù)據(jù)庫腳本
Quartz數(shù)據(jù)庫有11張表,既支持Mysql,也支持Oracle
Mysql
/* Navicat MySQL Data Transfer Source Server : 10.19.34.3_ehr_admin Source Server Version : 50639 Source Host : 10.19.34.3:3306 Source Database : attend_base_dev Target Server Type : MYSQL Target Server Version : 50639 File Encoding : 65001 Date: 2020-08-28 16:29:36 */ -- SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `qrtz_CALENDARS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_CALENDARS`; CREATE TABLE `qrtz_CALENDARS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `CALENDAR_NAME` varchar(200) NOT NULL, `CALENDAR` blob NOT NULL, PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='日歷信息'; -- ---------------------------- -- Records of qrtz_CALENDARS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_FIRED_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_FIRED_TRIGGERS`; CREATE TABLE `qrtz_FIRED_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `ENTRY_ID` varchar(95) NOT NULL COMMENT '組標識', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '當前實例的名稱', `FIRED_TIME` bigint(13) NOT NULL COMMENT '當前執(zhí)行時間', `SCHED_TIME` bigint(13) NOT NULL COMMENT '計劃時間', `PRIORITY` int(11) NOT NULL COMMENT '權(quán)重', `STATE` varchar(16) NOT NULL COMMENT '狀態(tài):WAITING:等待 \r\nPAUSED:暫停 \r\nACQUIRED:正常執(zhí)行 \r\nBLOCKED:阻塞 \r\nERROR:錯誤', `JOB_NAME` varchar(200) DEFAULT NULL COMMENT '作業(yè)名稱', `JOB_GROUP` varchar(200) DEFAULT NULL COMMENT '作業(yè)組', `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否并行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否要求喚醒', 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 COMMENT='保存已經(jīng)觸發(fā)的觸發(fā)器狀態(tài)信息'; -- ---------------------------- -- Records of qrtz_FIRED_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_JOB_DETAILS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_JOB_DETAILS`; CREATE TABLE `qrtz_JOB_DETAILS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `JOB_NAME` varchar(200) NOT NULL COMMENT '集群中job的名字', `JOB_GROUP` varchar(200) NOT NULL COMMENT '集群中job的所屬組的名字', `DESCRIPTION` varchar(250) DEFAULT NULL COMMENT '描述', `JOB_CLASS_NAME` varchar(250) NOT NULL COMMENT '作業(yè)程序類名', `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否并行', `IS_UPDATE_DATA` varchar(1) NOT NULL COMMENT '是否更新', `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否要求喚醒', `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 COMMENT='job 詳細信息'; -- ---------------------------- -- Records of qrtz_JOB_DETAILS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_LOCKS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_LOCKS`; CREATE TABLE `qrtz_LOCKS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `LOCK_NAME` varchar(40) NOT NULL COMMENT '鎖名稱', PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存儲程序的悲觀鎖的信息(假如使用了悲觀鎖) '; -- ---------------------------- -- Records of qrtz_LOCKS -- ---------------------------- -- Table structure for `qrtz_PAUSED_TRIGGER_GRPS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_PAUSED_TRIGGER_GRPS`; CREATE TABLE `qrtz_PAUSED_TRIGGER_GRPS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存放暫停掉的觸發(fā)器'; -- ---------------------------- -- Records of qrtz_PAUSED_TRIGGER_GRPS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_SCHEDULER_STATE` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SCHEDULER_STATE`; CREATE TABLE `qrtz_SCHEDULER_STATE` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '實例名稱', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '最后的檢查時間', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '檢查間隔', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='調(diào)度器狀態(tài)'; -- ---------------------------- -- Records of qrtz_SCHEDULER_STATE -- ---------------------------- -- Table structure for `qrtz_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_TRIGGERS`; CREATE TABLE `qrtz_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `JOB_NAME` varchar(200) NOT NULL COMMENT '作業(yè)名稱', `JOB_GROUP` varchar(200) NOT NULL COMMENT '作業(yè)組', `DESCRIPTION` varchar(250) DEFAULT NULL COMMENT '描述', `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '下次執(zhí)行時間', `PREV_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '前一次', `PRIORITY` int(11) DEFAULT NULL COMMENT '優(yōu)先權(quán)', `TRIGGER_STATE` varchar(16) NOT NULL COMMENT '觸發(fā)器狀態(tài)', `TRIGGER_TYPE` varchar(8) NOT NULL COMMENT '觸發(fā)器類型', `START_TIME` bigint(13) NOT NULL COMMENT '開始時間', `END_TIME` bigint(13) DEFAULT NULL COMMENT '結(jié)束時間', `CALENDAR_NAME` varchar(200) DEFAULT NULL COMMENT '日歷名稱', `MISFIRE_INSTR` smallint(2) DEFAULT NULL COMMENT '失敗次數(shù)', `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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='觸發(fā)器'; -- ---------------------------- -- Records of qrtz_TRIGGERS -- ---------------------------- -- Table structure for `qrtz_SIMPLE_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SIMPLE_TRIGGERS`; CREATE TABLE `qrtz_SIMPLE_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重復次數(shù)', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重復間隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '觸發(fā)次數(shù)', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='簡單的觸發(fā)器'; -- ---------------------------- -- Records of qrtz_SIMPLE_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_SIMPROP_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SIMPROP_TRIGGERS`; CREATE TABLE `qrtz_SIMPROP_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存儲CalendarIntervalTrigger和DailyTimeIntervalTrigger兩種類型的觸發(fā)器'; -- ---------------------------- -- Records of qrtz_SIMPROP_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_BLOB_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_BLOB_TRIGGERS`; CREATE TABLE `qrtz_BLOB_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以Blob 類型存儲的觸發(fā)器'; -- ---------------------------- -- Records of qrtz_BLOB_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_CRON_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_CRON_TRIGGERS`; CREATE TABLE `qrtz_CRON_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT '觸發(fā)器名稱', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '觸發(fā)器組', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT '時間表達式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '時區(qū)ID nvarchar 80', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='定時觸發(fā)器'; -- ---------------------------- -- Records of qrtz_CRON_TRIGGERS -- ---------------------------- Oracle create table QRTZ_CALENDARS ( sched_name VARCHAR2(120) not null, calendar_name VARCHAR2(200) not null, calendar BLOB not null ); alter table QRTZ_CALENDARS add constraint PK_QRTZ_CALENDARS primary key (SCHED_NAME, CALENDAR_NAME); create table QRTZ_FIRED_TRIGGERS ( sched_name VARCHAR2(120) not null, entry_id VARCHAR2(95) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, instance_name VARCHAR2(200) not null, fired_time NUMBER(13) not null, sched_time NUMBER(13) not null, priority INTEGER not null, state VARCHAR2(16) not null, job_name VARCHAR2(200), job_group VARCHAR2(200), is_nonconcurrent VARCHAR2(1), requests_recovery VARCHAR2(1) ); alter table QRTZ_FIRED_TRIGGERS add constraint PK_QRTZ_FIRED_TRIGGERS primary key (SCHED_NAME, ENTRY_ID); create table QRTZ_JOB_DETAILS ( sched_name VARCHAR2(120) not null, job_name VARCHAR2(200) not null, job_group VARCHAR2(200) not null, description VARCHAR2(250), job_class_name VARCHAR2(250) not null, is_durable VARCHAR2(1) not null, is_nonconcurrent VARCHAR2(1) not null, is_update_data VARCHAR2(1) not null, requests_recovery VARCHAR2(1) not null, job_data BLOB ); alter table QRTZ_JOB_DETAILS add constraint PK_QRTZ_JOB_DETAILS primary key (SCHED_NAME, JOB_NAME, JOB_GROUP); create table QRTZ_LOCKS ( sched_name VARCHAR2(120) not null, lock_name VARCHAR2(40) not null ); alter table QRTZ_LOCKS add constraint PK_QRTZ_LOCKS primary key (SCHED_NAME, LOCK_NAME); create table QRTZ_PAUSED_TRIGGER_GRPS ( sched_name VARCHAR2(120) not null, trigger_group VARCHAR2(200) not null ); alter table QRTZ_PAUSED_TRIGGER_GRPS add constraint PK__TRIGGER_GRPS primary key (SCHED_NAME, TRIGGER_GROUP); create table QRTZ_SCHEDULER_STATE ( sched_name VARCHAR2(120) not null, instance_name VARCHAR2(200) not null, last_checkin_time NUMBER(13) not null, checkin_interval NUMBER(13) not null ); alter table QRTZ_SCHEDULER_STATE add constraint PK_QRTZ_SCHEDULER_STATE primary key (SCHED_NAME, INSTANCE_NAME); create table QRTZ_TRIGGERS ( sched_name VARCHAR2(120) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, job_name VARCHAR2(200) not null, job_group VARCHAR2(200) not null, description VARCHAR2(250), next_fire_time NUMBER(13), prev_fire_time NUMBER(13), priority INTEGER, trigger_state VARCHAR2(16) not null, trigger_type VARCHAR2(8) not null, start_time NUMBER(13) not null, end_time NUMBER(13), calendar_name VARCHAR2(200), misfire_instr NUMBER(2), job_data BLOB ); alter table QRTZ_TRIGGERS add constraint PK_QRTZ_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); create table QRTZ_SIMPLE_TRIGGERS ( sched_name VARCHAR2(120) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, repeat_count NUMBER(7) not null, repeat_interval NUMBER(12) not null, times_triggered NUMBER(10) not null ); alter table QRTZ_SIMPLE_TRIGGERS add constraint PK_QRTZ_SIMPLE_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); create table QRTZ_SIMPROP_TRIGGERS ( sched_name VARCHAR2(120) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, str_prop_1 VARCHAR2(512), str_prop_2 VARCHAR2(512), str_prop_3 VARCHAR2(512), int_prop_1 INTEGER, int_prop_2 INTEGER, long_prop_1 NUMBER, long_prop_2 NUMBER, dec_prop_1 NUMBER(13,4), dec_prop_2 NUMBER(13,4), bool_prop_1 VARCHAR2(1), bool_prop_2 VARCHAR2(1) ); alter table QRTZ_SIMPROP_TRIGGERS add constraint PK_QRTZ_SIMPROP_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); create table QRTZ_BLOB_TRIGGERS ( sched_name VARCHAR2(120) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, blob_data BLOB ); alter table QRTZ_BLOB_TRIGGERS add constraint PK_QRTZ_BLOB_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); create table QRTZ_CRON_TRIGGERS ( sched_name VARCHAR2(120) not null, trigger_name VARCHAR2(200) not null, trigger_group VARCHAR2(200) not null, cron_expression VARCHAR2(200) not null, time_zone_id VARCHAR2(80) ); alter table QRTZ_CRON_TRIGGERS add constraint PK_QRTZ_CRON_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); delete from QRTZ_JOB_DETAILS; delete from QRTZ_CRON_TRIGGERS; delete from QRTZ_BLOB_TRIGGERS; delete from QRTZ_CALENDARS; delete from QRTZ_FIRED_TRIGGERS; delete from QRTZ_LOCKS; delete from QRTZ_PAUSED_TRIGGER_GRPS; delete from QRTZ_SCHEDULER_STATE; delete from QRTZ_SIMPLE_TRIGGERS; delete from QRTZ_SIMPROP_TRIGGERS; delete from QRTZ_TRIGGERS;
Maven
我這里后臺使用的是Springboot2.1
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
application.yml
quartz:
#quartz相關(guān)屬性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler #調(diào)度器的實例名
instanceId: AUTO #調(diào)度器編號自動生成
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: qrtz_ #數(shù)據(jù)庫表名前綴
isClustered: true #開啟分布式部署
clusterCheckinInterval: 10000 #分布式節(jié)點有效性檢查時間間隔,單位:秒
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool #自帶的線程池實現(xiàn)類
threadCount: 10 #開啟10個線程
threadPriority: 5 #工作者線程的優(yōu)先級
threadsInheritContextClassLoaderOfInitializingThread: true
#數(shù)據(jù)庫方式
job-store-type: jdbc
Bean
import org.quartz.JobDataMap;
import java.util.Date;
/**
* @program: QuartzBean
* @description:
* @author: Yuwl
* @create: 2020-06-02 18:36
**/
public class QuartzBean {
/** 任務(wù)id */
private String id;
/** 任務(wù)名稱 */
private String jobName;
/** 任務(wù)組 */
private String jobGroup;
/** 任務(wù)執(zhí)行類 */
private String jobClass;
/** 任務(wù)狀態(tài) 啟動還是暫停*/
private Integer status;
/**
* 任務(wù)開始時間
*/
private Date startTime;
/**
* 任務(wù)循環(huán)間隔-單位:分鐘
*/
private Integer interval;
/**
* 任務(wù)結(jié)束時間
*/
private Date endTime;
/** 任務(wù)運行時間表達式 */
private String cronExpression;
private JobDataMap jobDataMap;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobClass() {
return jobClass;
}
public void setJobClass(String jobClass) {
this.jobClass = jobClass;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Integer getInterval() {
return interval;
}
public void setInterval(Integer interval) {
this.interval = interval;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public JobDataMap getJobDataMap() {
return jobDataMap;
}
public void setJobDataMap(JobDataMap jobDataMap) {
this.jobDataMap = jobDataMap;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
}
Service
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.framework.quartz.QuartzBean;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @program: QuartzJobService
* @description:
* @author: Yuwl
* @create: 2020-07-21 17:00
**/
@Service
public class QuartzJobService {
@Autowired
private Scheduler scheduler;
/**
* 創(chuàng)建定時任務(wù)Simple
* quartzBean.getInterval()==null表示單次提醒,
* 否則循環(huán)提醒(quartzBean.getEndTime()!=null)
* @param quartzBean
*/
public void createScheduleJobSimple(QuartzBean quartzBean) throws Exception{
//獲取到定時任務(wù)的執(zhí)行類 必須是類的絕對路徑名稱
//定時任務(wù)類需要是job類的具體實現(xiàn) QuartzJobBean是job的抽象類。
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
// 構(gòu)建定時任務(wù)信息
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
.setJobData(quartzBean.getJobDataMap())
.build();
// 設(shè)置定時任務(wù)執(zhí)行方式
SimpleScheduleBuilder simpleScheduleBuilder = null;
if (quartzBean.getInterval() == null) { //單次
simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
} else { //循環(huán)
simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());
}
// 構(gòu)建觸發(fā)器trigger
Trigger trigger = null;
if (quartzBean.getInterval() == null) { //單次
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
.withSchedule(simpleScheduleBuilder)
.startAt(quartzBean.getStartTime())
.build();
} else { //循環(huán)
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
.withSchedule(simpleScheduleBuilder)
.startAt(quartzBean.getStartTime())
.endAt(quartzBean.getEndTime())
.build();
}
scheduler.scheduleJob(jobDetail, trigger);
}
/**
* 創(chuàng)建定時任務(wù)Cron
* 定時任務(wù)創(chuàng)建之后默認啟動狀態(tài)
* @param quartzBean 定時任務(wù)信息類
* @throws Exception
*/
public void createScheduleJobCron(QuartzBean quartzBean) throws Exception{
//獲取到定時任務(wù)的執(zhí)行類 必須是類的絕對路徑名稱
//定時任務(wù)類需要是job類的具體實現(xiàn) QuartzJobBean是job的抽象類。
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
// 構(gòu)建定時任務(wù)信息
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).setJobData(quartzBean.getJobDataMap()).build();
// 設(shè)置定時任務(wù)執(zhí)行方式
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
// 構(gòu)建觸發(fā)器trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
}
/**
* 根據(jù)任務(wù)名稱暫停定時任務(wù)
* @param jobName 定時任務(wù)名稱
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @throws Exception
*/
public void pauseScheduleJob(String jobName,String jobGroup) throws Exception{
JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
scheduler.pauseJob(jobKey);
}
/**
* 根據(jù)任務(wù)名稱恢復定時任務(wù)
* @param jobName 定時任務(wù)名
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @throws SchedulerException
*/
public void resumeScheduleJob(String jobName,String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
scheduler.resumeJob(jobKey);
}
/**
* 根據(jù)任務(wù)名稱立即運行一次定時任務(wù)
* @param jobName 定時任務(wù)名稱
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @throws SchedulerException
*/
public void runOnce(String jobName,String jobGroup) throws Exception{
JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
scheduler.triggerJob(jobKey);
}
/**
* 更新定時任務(wù)Simple
* @param quartzBean 定時任務(wù)信息類
* @throws SchedulerException
*/
public void updateScheduleJobSimple(QuartzBean quartzBean) throws Exception {
//獲取到對應任務(wù)的觸發(fā)器
TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null);
// 設(shè)置定時任務(wù)執(zhí)行方式
SimpleScheduleBuilder simpleScheduleBuilder = null;
if (quartzBean.getInterval() == null) { //單次
simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
} else { //循環(huán)
simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());
}
// 構(gòu)建觸發(fā)器trigger
Trigger trigger = null;
if (quartzBean.getInterval() == null) { //單次
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
.withSchedule(simpleScheduleBuilder)
.startAt(quartzBean.getStartTime())
.build();
} else { //循環(huán)
TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
.withSchedule(simpleScheduleBuilder)
.startAt(quartzBean.getStartTime())
.endAt(quartzBean.getEndTime())
.build();
}
//重置對應的job
scheduler.rescheduleJob(triggerKey, trigger);
}
/**
* 更新定時任務(wù)Cron
* @param quartzBean 定時任務(wù)信息類
* @throws SchedulerException
*/
public void updateScheduleJobCron(QuartzBean quartzBean) throws Exception {
//獲取到對應任務(wù)的觸發(fā)器
TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
//設(shè)置定時任務(wù)執(zhí)行方式
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
//重新構(gòu)建任務(wù)的觸發(fā)器trigger
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//重置對應的job
scheduler.rescheduleJob(triggerKey, trigger);
}
/**
* 根據(jù)定時任務(wù)名稱從調(diào)度器當中刪除定時任務(wù)
* @param jobName 定時任務(wù)名稱
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @throws SchedulerException
*/
public void deleteScheduleJob(String jobName,String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
scheduler.deleteJob(jobKey);
}
/**
* 獲取任務(wù)狀態(tài)
* @param jobName
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @return
* (" BLOCKED ", " 阻塞 ");
* ("COMPLETE", "完成");
* ("ERROR", "出錯");
* ("NONE", "不存在");
* ("NORMAL", "正常");
* ("PAUSED", "暫停");
*/
public String getScheduleJobStatus(String jobName,String jobGroup) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
return state.name();
}
/**
* 根據(jù)定時任務(wù)名稱來判斷任務(wù)是否存在
* @param jobName 定時任務(wù)名稱
* @param jobGroup 任務(wù)組(沒有分組傳值null)
* @throws SchedulerException
*/
public Boolean checkExistsScheduleJob(String jobName,String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
return scheduler.checkExists(jobKey);
}
/**
* 根據(jù)任務(wù)組刪除定時任務(wù)
* @param jobGroup 任務(wù)組
* @throws SchedulerException
*/
public Boolean deleteGroupJob(String jobGroup) throws Exception {
GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup);
Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher);
List<JobKey> jobkeyList = new ArrayList<JobKey>();
jobkeyList.addAll(jobkeySet);
return scheduler.deleteJobs(jobkeyList);
}
/**
* 根據(jù)任務(wù)組批量刪除定時任務(wù)
* @param jobkeyList
* @throws SchedulerException
*/
public Boolean batchDeleteGroupJob(List<JobKey> jobkeyList) throws Exception {
return scheduler.deleteJobs(jobkeyList);
}
/**
* 根據(jù)任務(wù)組批量查詢出jobkey
* @param jobGroup 任務(wù)組
* @throws SchedulerException
*/
public void batchQueryGroupJob(List<JobKey> jobkeyList,String jobGroup) throws Exception {
GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup);
Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher);
jobkeyList.addAll(jobkeySet);
}
}
Job
package com.quartz.demo.job
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @program: job
* @description:
* @author: Yuwl
* @create: 2020-06-02 18:07
**/
@Component
public class MyTask extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JobKey jobKey = context.getJobDetail().getKey();
JobDataMap map = context.getJobDetail().getJobDataMap();
String userId = map.getString("userId");
System.out.println("SimpleJob says: " + jobKey + ", userId: " + userId + " executing at " + new Date());
}
}
Controller
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.quartz.QuartzBean;
import com.ruoyi.framework.quartz.service.QuartzJobService;
import org.quartz.JobDataMap;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.util.Date;
/**
* @program: JobController
* @description:
* @author: Yuwl
* @create: 2020-07-21 17:08
**/
@RestController
@RequestMapping("/api/quartz/")
public class JobController {
@Autowired
private QuartzJobService quartzJobService;
//創(chuàng)建&啟動
@GetMapping("startSimpleJob")
public String startSimpleJob() throws SchedulerException, ClassNotFoundException, ParseException {
QuartzBean quartzBean = new QuartzBean();
quartzBean.setJobClass("com.quartz.demo.job.MyTask");
quartzBean.setJobName("job1");
JobDataMap map = new JobDataMap();
map.put("userId", "123456");
quartzBean.setJobDataMap(map);
Date now = new Date();
quartzBean.setStartTime(DateUtils.addSeconds(now, 10));
quartzBean.setInterval(10);
quartzBean.setEndTime(DateUtils.addMinutes(now, 1));
try {
quartzJobService.createScheduleJobSimple(quartzBean);
} catch (Exception e) {
e.printStackTrace();
}
return "startJob Success!";
}
/**
* 創(chuàng)建cron Job
* @param quartzBean
* @return
*/
@RequestMapping("/createCronJob")
@ResponseBody
public String createJob(QuartzBean quartzBean) {
try {
//進行測試所以寫死
quartzBean.setJobClass("com.quartz.demo.job.MyTask");
quartzBean.setJobName("job1");
quartzBean.setCronExpression("*/5 * * * * ?");
quartzJobService.createScheduleJobCron(quartzBean);
} catch (Exception e) {
return "創(chuàng)建失敗";
}
return "創(chuàng)建成功";
}
/**
* 暫停job
* @return
*/
@RequestMapping(value = {"/pauseJob/{jobName}","/pauseJob/{jobName}/{jobGroup}"})
@ResponseBody
public String pauseJob(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
try {
quartzJobService.pauseScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
} catch (Exception e) {
return "暫停失敗";
}
return "暫停成功";
}
@RequestMapping(value = {"/resume/{jobName}","/resume/{jobName}/{jobGroup}"})
@ResponseBody
public String resume(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
try {
quartzJobService.resumeScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
} catch (Exception e) {
return "啟動失敗";
}
return "啟動成功";
}
@RequestMapping(value = {"/delete/{jobName}","/delete/{jobName}/{jobGroup}"})
public String delete(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
try {
quartzJobService.deleteScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
} catch (Exception e) {
return "刪除失敗";
}
return "刪除成功";
}
@RequestMapping(value = {"/check/{jobName}","/check/{jobName}/{jobGroup}"})
public String check(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
try {
if(quartzJobService.checkExistsScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null)){
return "存在定時任務(wù):"+jobName;
}else{
return "不存在定時任務(wù):"+jobName;
}
} catch (Exception e) {
return "查詢?nèi)蝿?wù)失敗";
}
}
@RequestMapping(value = {"/status/{jobName}","/status/{jobName}/{jobGroup}"})
@ResponseBody
public String status(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
try {
return quartzJobService.getScheduleJobStatus(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
} catch (Exception e) {
return "獲取狀態(tài)失敗";
}
//return "獲取狀態(tài)成功";
}
}
測試
http://localhost:8080/api/quartz/startSimpleJob
到此這篇關(guān)于Springboot2.x+Quartz分布式集群的實現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot2.x Quartz分布式集群內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+Quartz+數(shù)據(jù)庫存儲的完美集合
- SpringBoot自動配置Quartz的實現(xiàn)步驟
- SpringBoot+SpringBatch+Quartz整合定時批量任務(wù)方式
- SpringBoot集成Quartz實現(xiàn)定時任務(wù)的方法
- 淺談SpringBoot集成Quartz動態(tài)定時任務(wù)
- Springboot整個Quartz實現(xiàn)動態(tài)定時任務(wù)的示例代碼
- springboot+Quartz實現(xiàn)任務(wù)調(diào)度的示例代碼
- SpringBoot異步調(diào)用方法并接收返回值
- SpringBoot開啟異步調(diào)用方法
- SpringBoot整合Quartz及異步調(diào)用的案例
相關(guān)文章
Spring依賴注入Dependency Injection的三種方式
依賴注入(Dependency Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個概念。具體含義是:當某個角色(可能是一個Java實例,調(diào)用者)需要另一個角色(另一個Java實例,被調(diào)用者)的協(xié)助時,在傳統(tǒng)的程序設(shè)計過程中,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實例2023-02-02
詳解java.lang.NumberFormatException錯誤及解決辦法
這篇文章主要介紹了詳解java.lang.NumberFormatException錯誤及解決辦法,本文詳解的介紹了錯誤的解決方法,感興趣的可以一起來了解一下2020-05-05

