Springboot2.x+Quartz分布式集群的实现

网友投稿 350 2022-11-20


Springboot2.x+Quartz分布式集群的实现

生产环境一般都是多节点高可用,Springboot本身自带有定时任务功能,但我们项目需求要求能对定时任务进行增,删,改,查。所以考虑引进Quartz,引入Quartz就需要考虑分布式集群,所以就有了这篇文章。

数据库脚本

Quartz数据库有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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`INSTANCE_NAME` varchar(200) NOT NULL COMMENT '当前实例的名称',

`FIRED_TIME` bigint(13) NOT NULL COMMENT '当前执行时间',

`SCHED_TIME` bigint(13) NOT NULL COMMENT '计划时间',

`PRIORITY` int(11) NOT NULL COMMENT '权重',

`STATE` varchar(16) NOT NULL COMMENT '状态:WAITING:等待 \r\nPAUSED:暂停 \r\nACQUIRED:正常执行 \r\nBLOCKED:阻塞 \r\nERROR:错误',

`JOB_NAME` varchar(200) DEFAULT NULL COMMENT '作业名称',

`JOB_GROUP` varchar(200) DEFAULT NULL COMMENT '作业组',

`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='保存已经触发的触发器状态信息';

-- ----------------------------

-- 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 '作业程序类名',

`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`http:// 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 '触发器组',

PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存放暂停掉的触发器';

-- ----------------------------

-- 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='调度器状态';

-- ----------------------------

-- 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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`JOB_NAME` varchar(200) NOT NULL COMMENT '作业名称',

`JOB_GROUP` varchar(200) NOT NULL COMMENT '作业组',

`DESCRIPTION` varchar(250) DEFAULT NULL COMMENT '描述',

`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '下次执行时间',

`PREV_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '前一次',

`PRIORITY` int(11) DEFAULT NULL COMMENT '优先权',

`TRIGGER_STATE` varchar(16) NOT NULL COMMENT '触发器状态',

`TRIGGER_TYPE` varchar(8) NOT NULL COMMENT '触发器类型',

`START_TIME` bigint(13) NOT NULL COMMENT '开始时间',

`END_TIME` bigint(13) DEFAULT NULL COMMENT '结束时间',

`CALENDAR_NAME` varchar(200) DEFAULT NULL COMMENT '日历名称',

`MISFIRE_INSTR` smallint(2) DEFAULT NULL COMMENT '失败次数',

`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='触发器';

-- ----------------------------

-- 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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数',

`REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔',

`TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '触发次数',

PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='简单的触发器';

-- ----------------------------

-- 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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`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两种类型的触发器';

-- ----------------------------

-- 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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`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 类型存储的触发器';

-- ----------------------------

-- 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 '触发器名称',

`TRIGGER_GROUP` varchar(200) NOT NULL COMMENT '触发器组',

`CRON_EXPRESSION` varchar(120) NOT NULL COMMENT '时间表达式',

`TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区ID nvarchar 80',

PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='定时触发器';

-- ----------------------------

-- 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_LOChttp://KS

(

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

org.springframework.boot

spring-boot-starter-quartz

application.yml

quartz:

#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 #开启10个线程

threadsInheritContextClassLoaderOfInitializingThread: true

#数据库方式

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 {

/** 任务id */

private String id;

/** 任务名称 */

private String jobName;

/** 任务组 */

private String jobGroup;

/** 任务执行类 */

private String jobClass;

/** 任务状态 启动还是暂停*/

private Integer status;

/**

* 任务开始时间

*/

private Date startTime;

/**

* 任务循环间隔-单位:分钟

*/

private Integer interval;

/**

* 任务结束时间

*/

private Date endTime;

/** 任务运行时间表达式 */

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;

/**

* 创建定时任务Simple

* quartzBean.getInterval()==null表示单次提醒,

* 否则循环提醒(quartzBean.getEndTime()!=null)

* @param quartzBean

*/

public void createScheduleJobSimple(QuartzBean quartzBean) throws Exception{

//获取到定时任务的执行类 必须是类的绝对路径名称

//定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。

Class extends Job> jobClass = (Class extends Job>) Class.forName(quartzBean.getJobClass());

// 构建定时任务信息

JobDetail jobDetail = JobBuilder.newJob(jobClass)

.withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)

.setJobData(quartzBean.getJobDataMap())

.build();

// 设置定时任务执行方式

SimpleScheduleBuilder simpleScheduleBuilder = null;

if (quartzBean.getInterval() == null) { //单次

simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();

} else { //循环

simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());

}

// 构建触发器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 { //循环

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);

}

/**

* 创建定时任务Cron

* 定时任务创建之后默认启动状态

* @param quartzBean 定时任务信息类

* @throws Exception

*/

public void createScheduleJobCron(QuartzBean quartzBean) throws Exception{

//获取到定时任务的执行类 必须是类的绝对路径名称

//定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。

Class extends Job> jobClass = (Class extends Job>) Class.forName(quartzBean.getJobClass());

// 构建定时任务信息

JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).setJobData(quartzBean.getJobDataMap()).build();

// 设置定时任务执行方式

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());

// 构建触发器trigger

CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();

scheduler.scheduleJob(jobDetail, trigger);

}

/**

* 根据任务名称暂停定时任务

* @param jobName 定时任务名称

* @param jobGroup 任务组(没有分组传值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);

}

/**

* 根据任务名称恢复定时任务

* @param jobName 定时任务名

* @param jobGroup 任务组(没有分组传值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);

}

/**

* 根据任务名称立即运行一次定时任务

* @param jobName 定时任务名称

* @param jobGroup 任务组(没有分组传值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);

}

/**

* 更新定时任务Simple

* @param quartzBean 定时任务信息类

* @throws SchedulerException

*/

public void updateScheduleJobSimple(QuartzBean quartzBean) throws Exception {

//获取到对应任务的触发器

TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null);

// 设置定时任务执行方式

SimpleScheduleBuilder simpleScheduleBuilder = null;

if (quartzBean.getInterval() == null) { //单次

simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();

} else { //循环

simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());

}

// 构建触发器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 { //循环

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);

}

/**

* 更新定时任务Cron

* @param quartzBean 定时任务信息类

* @throws SchedulerException

*/

public void updateScheduleJobCron(QuartzBean quartzBean) throws Exception {

//获取到对应任务的触发器

TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());

//设置定时任务执行方式

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());

//重新构建任务的触发器trigger

CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

//重置对应的job

scheduler.rescheduleJob(triggerKey, trigger);

}

/**

* 根据定时任务名称从调度器当中删除定时任务

* @param jobName 定时任务名称

* @param jobGroup 任务组(没有分组传值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);

}

/**

* 获取任务状态

* @param jobName

* @param jobGroup 任务组(没有分组传值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();

}

/**

* 根据定时任务名称来判断任务是否存在

* @param jobName 定时任务名称

* @param jobGroup 任务组(没有分组传值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);

}

/**

* 根据任务組刪除定時任务

* @param jobGroup 任务组

* @throws SchedulerException

*/

public Boolean deleteGroupJob(String jobGroup) throws Exception {

GroupMatcher matcher = GroupMatcher.groupEquals(jobGroup);

Set jobkeySet = scheduler.getJobKeys(matcher);

List jobkeyList = new ArrayList();

jobkeyList.addAll(jobkeySet);

return scheduler.deleteJobs(jobkeyList);

}

/**

* 根据任务組批量刪除定時任务

* @param jobkeyList

* @throws SchedulerException

*/

public Boolean batchDeleteGroupJob(List jobkeyList) throws Exception {

return scheduler.deleteJobs(jobkeyList);

}

/**

* 根据任务組批量查询出jobkey

* @param jobGroup 任务组

* @throws SchedulerException

*/

public void batchQueryGroupJob(List jobkeyList,String jobGroup) throws Exception {

GroupMatcher matcher = GroupMatcher.groupEquals(jobGroup);

Set 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;

//创建&启动

@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!";

}

/**

* 创建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 "创建失败";

}

return "创建成功";

}

/**

* 暂停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 "存在定时任务:"+jobName;

}else{

return "不存在定时任务:"+jobName;

}

} catch (Exception e) {

return "查询任务失败";

}

}

@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 "获取状态失败";

}

//return "获取状态成功";

}

}

测试

http://localhost:8080/api/quartz/startSimpleJob


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:IntelliJ IDEA各种图标的含义
下一篇:SpringMVC方法返回值多种情况代码实例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~