SpringBoot整合Quartz定时任务
- 1、定时任务相关概念
- 2、SpringBoot集成Quartz
- 2.1、Quartz相关表
- 2.2、pom.xml
- 2.3、application.yml
- 2.4、java对任务增删改查
- 2.4.1、common相关配置类
- 2.4.2、pojo类
- 2.4.3、task类
- 2.4.4、Controller类
- 3、一些理解
- 3.1、Quartz的集群原理以及配置?
1、定时任务相关概念
SpringBoot中的@Schedule定时任务并不支持动态管理定时任务,且项目重启后,任务相当于重新创,实际重新创建对任务影响也不大。
而Quartz则支持对定时任务的创建,删除,修改,查询,很灵活的管理了定时任务,Quartz任务也支持分布式部署和任务信息持久化,重启项目后任务仍然存在。
2、SpringBoot集成Quartz
下面整合的代码,直接复制在企业级项目中使用即可,完全符合企业项目的使用,很灵活,很动态。
2.1、Quartz相关表
Quartz自定11张表,直接导入即可
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(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) 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(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),
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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) 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(190) 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(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 INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(190) NULL,
JOB_GROUP VARCHAR(190) 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(190) 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;
2.2、pom.xml
<dependencies>
<!--引入web starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>
2.3、application.yml
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/quartz_test?useUnicode=true&autoReconnect=true&failOverReadOnly=false&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL
quartz:
job-store-type: jdbc #数据库方式
jdbc:
initialize-schema: never #不初始化表结构
properties:
org:
quartz:
scheduler:
instanceId: AUTO #默认主机名和时间戳生成实例ID,可以是任何字符串,但对于所有调度程序来说,必须是唯一的 对应qrtz_scheduler_state INSTANCE_NAME字段
#instanceName: clusteredScheduler #quartzScheduler
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore # springboot>2.5.6后使用这个
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #仅为数据库制作了特定于数据库的代理
useProperties: false #以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题。
tablePrefix: qrtz_ #数据库表前缀
misfireThreshold: 60000 #在被认为“失火”之前,调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)。
clusterCheckinInterval: 5000 #设置此实例“检入”*与群集的其他实例的频率(以毫秒为单位)。影响检测失败实例的速度。
isClustered: true #打开群集功能
threadPool: #连接池
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
2.4、java对任务增删改查
2.4.1、common相关配置类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class InitHandler {
@Autowired
private TaskInitHandler taskInitHandler;
/**
* 系统初始化任务入口。
* 如果系统在启动时需要添加一些定时任务,把业务逻辑写到taskInitHandler.init()方法里即可
*/
@PostConstruct
public void init() {
taskInitHandler.init();
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TaskInitHandler {
public void init() {
log.info("初始化定时任务业务逻辑......");
}
}
import cn.yx.zg.pojo.QuartzBean;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 该类提供对quartz任务的创建、删除、查询、修改
*/
@Service
public class QuartzJobService {
@Resource
private Scheduler scheduler;
/**
* 查询定时任务列表
*
* @return
*/
public List<QuartzBean> getScheduleJobList() {
List<QuartzBean> list = new ArrayList<>();
try {
for (String groupJob : scheduler.getJobGroupNames()) {
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.<JobKey>groupEquals(groupJob))) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
QuartzBean quartzBean = new QuartzBean();
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
String cronExpression = "";
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
cronExpression = cronTrigger.getCronExpression();
quartzBean.setCronExpression(cronExpression);
}
quartzBean.setStartTime(trigger.getStartTime());
quartzBean.setEndTime(trigger.getEndTime());
quartzBean.setJobName(jobKey.getName());
quartzBean.setJobGroup(jobKey.getGroup());
quartzBean.setJobDescription(jobDetail.getDescription());
quartzBean.setJobStatus(triggerState.name());
quartzBean.setJobClass(jobDetail.getJobClass().toGenericString());
quartzBean.setJobDataMap(jobDetail.getJobDataMap());
list.add(quartzBean);
}
}
}
} catch (SchedulerException e) {
e.printStackTrace();
}
return list;
}
/**
* 创建简单调度任务
*
* @param quartzBean
* @throws Exception
*/
public void createScheduleSimpleJob(QuartzBean quartzBean) throws Exception {
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
//job
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.setJobData(quartzBean.getJobDataMap())
.withDescription(quartzBean.getJobDescription())
.build();
//trigger
Trigger trigger = null;
//单次还是循环
if (quartzBean.getInterval() == null) {
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionNextWithExistingCount())
.startAt(quartzBean.getStartTime())
.build();
} else {
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(quartzBean.getInterval())
.withMisfireHandlingInstructionNextWithExistingCount())
.startAt(quartzBean.getStartTime())
.endAt(quartzBean.getEndTime())
.build();
}
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
}
/**
* 创建cron调度任务
*
* @param quartzBean
* @throws Exception
*/
public void createScheduleCronJob(QuartzBean quartzBean) throws Exception {
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
// job
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.setJobData(quartzBean.getJobDataMap())
.withDescription(quartzBean.getJobDescription())
.build();
// trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.withSchedule(CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression()))
.build();
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
}
/**
* 暂停任务
*
* @param jobName
* @param jobGroup
* @throws Exception
*/
public void pauseScheduleJob(String jobName, String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
scheduler.pauseJob(jobKey);
}
/**
* 立即执行任务
*
* @param jobName
* @param jobGroup
* @throws Exception
*/
public void runJob(String jobName, String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
scheduler.triggerJob(jobKey);
}
/**
* 更新简单任务
*
* @param quartzBean
* @throws Exception
*/
public void updateScheduleSimpleJob(QuartzBean quartzBean) throws Exception {
//原任务触发器
TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName(), quartzBean.getJobGroup());
//trigger
Trigger trigger = null;
//单次还是循环
if (quartzBean.getInterval() == null) {
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionNextWithExistingCount())
.startAt(quartzBean.getStartTime())
.build();
} else {
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName(), quartzBean.getJobGroup())
.withSchedule(SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval()).withMisfireHandlingInstructionNextWithExistingCount())
.startAt(quartzBean.getStartTime())
.endAt(quartzBean.getEndTime())
.build();
}
//重置对应的job
scheduler.rescheduleJob(triggerKey, trigger);
//用该方法一样可以修改定时任务
//scheduler.scheduleJob(jobDetail, trigger, true);
}
/**
* 更新定时任务Cron
*
* @param quartzBean 定时任务信息类
* @throws SchedulerException
*/
public void updateScheduleCronJob(QuartzBean quartzBean) throws Exception {
//原任务触发器
TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
// trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzBean.getJobName())
.withSchedule(CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression()))
.build();
//重置对应的job
scheduler.rescheduleJob(triggerKey, trigger);
}
/**
* 删除定时任务
*
* @param jobName
* @param jobGroup
* @throws Exception
*/
public void deleteScheduleJob(String jobName, String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
scheduler.deleteJob(jobKey);
}
/**
* 获取任务状态
* (" BLOCKED ", " 阻塞 ");
* ("COMPLETE", "完成");
* ("ERROR", "出错");
* ("NONE", "不存在");
* ("NORMAL", "正常");
* ("PAUSED", "暂停");
*/
public String getScheduleJobStatus(String jobName, String jobGroup) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
return state.name();
}
/**
* 检查任务是否存在
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
public Boolean checkExistsScheduleJob(String jobName, String jobGroup) throws Exception {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
return scheduler.checkExists(jobKey);
}
}
2.4.2、pojo类
import lombok.Data;
import org.quartz.JobDataMap;
import java.util.Date;
@Data
public class QuartzBean {
private String id;
private String jobName;
private String jobGroup;
private String jobDescription;
private String jobClass;
private String jobStatus;
/**
* 设置表示指定时间后任务开始执行
* 一般都是设置当前时间,表示立即执行
*/
private Date startTime;
/**
* 为null表示任务执行一次
* 为数字n表示每隔n秒后执行一次
*/
private Integer interval;
/**
* 表示在指定时间后任务结束
* 如果不设置,表示任务不会结束,
* 一般我们都会默认为null
*/
private Date endTime;
private String cronExpression;
private JobDataMap jobDataMap;
}
2.4.3、task类
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
public class MyTask implements Job {
@Override
public void execute(JobExecutionContext context) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
log.info("springboot-quartz-cluster-a" + ">>" + sdf.format(new Date()) + ":" + context.getJobDetail().getKey() + "执行中..." + context.getJobDetail().getDescription());
JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
log.info(mergedJobDataMap.getString("jobDataMapParam"));
}
}
2.4.4、Controller类
import cn.yx.zg.common.QuartzJobService;
import cn.yx.zg.pojo.QuartzBean;
import org.quartz.JobDataMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@RestController
public class QuartzJobController {
@Resource
private QuartzJobService quartzJobService;
/**
* 查询定时任务列表
*
* @return
*/
@GetMapping("get")
public List<QuartzBean> getQuartzList() {
return quartzJobService.getScheduleJobList();
}
/**
* 创建简单的任务
*
* @param jobName 任务名称
* @param jobGroup 任务组名称
* @param jobDescription 任务描述
* @return
* @throws Exception
*/
@GetMapping("createSimpleJob")
public String createSimpleJob(String jobName, String jobGroup, String jobDescription) throws Exception {
QuartzBean quartzBean = new QuartzBean();
quartzBean.setJobClass("cn.yx.zg.task.MyTask");
quartzBean.setJobName(jobName);
quartzBean.setJobGroup(jobGroup);
quartzBean.setJobDescription(jobDescription);
JobDataMap map = new JobDataMap();
map.put("jobDataMapParam", "aaa");
quartzBean.setJobDataMap(map);
//10s中后开始
Calendar newTimeStart = Calendar.getInstance();
newTimeStart.setTime(new Date());
newTimeStart.add(Calendar.SECOND, 10);
quartzBean.setStartTime(newTimeStart.getTime());
//50s后结束
Calendar newTimeEnd = Calendar.getInstance();
newTimeEnd.setTime(new Date());
newTimeEnd.add(Calendar.SECOND, 50);
quartzBean.setEndTime(newTimeEnd.getTime());
quartzBean.setEndTime(null);
//每隔3秒钟一次
quartzBean.setInterval(3);
quartzJobService.createScheduleSimpleJob(quartzBean);
return "SUCCESS";
}
/**
* 获取任务状态
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
@GetMapping("/getScheduleJobStatus")
public String getScheduleJobStatus(String jobName, String jobGroup) throws Exception {
/**
* ("BLOCKED", " 阻塞 ");
* ("COMPLETE", "完成");
* ("ERROR", "出错");
* ("NONE", "不存在");
* ("NORMAL", "正常");
* ("PAUSED", "暂停");
*/
return quartzJobService.getScheduleJobStatus(jobName, jobGroup);
}
/**
* 创建Cron的任务
*
* @param jobName
* @param jobGroup
* @param jobDescription
* @return
* @throws Exception
*/
@GetMapping("/createCronJob")
public String createCronJob(String jobName, String jobGroup, String jobDescription) throws Exception {
QuartzBean quartzBean = new QuartzBean();
quartzBean.setJobClass("cn.yx.zg.task.MyTask");
quartzBean.setJobName(jobName);
quartzBean.setJobGroup(jobGroup);
quartzBean.setJobDescription(jobDescription);
quartzBean.setCronExpression("*/10 * * * * ?");
JobDataMap map = new JobDataMap();
map.put("jobDataMapParam", "aaa");
quartzBean.setJobDataMap(map);
quartzJobService.createScheduleCronJob(quartzBean);
return "SUCCESS";
}
/**
* 删除任务
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
@GetMapping(value = "/delete")
public String delete(String jobName, String jobGroup) throws Exception {
quartzJobService.deleteScheduleJob(jobName, jobGroup);
return "SUCCESS";
}
/**
* 立即执行定时任务
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
@GetMapping(value = "/runJob")
public String runJob(String jobName, String jobGroup) throws Exception {
quartzJobService.runJob(jobName, jobGroup);
return "SUCCESS";
}
/**
* 暂停定时任务
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
@GetMapping(value = "/pauseScheduleJob")
public String pauseScheduleJob(String jobName, String jobGroup) throws Exception {
quartzJobService.pauseScheduleJob(jobName, jobGroup);
return "SUCCESS";
}
/**
* 校验定时任务是否存在
*
* @param jobName
* @param jobGroup
* @return
* @throws Exception
*/
@GetMapping(value = "check")
public String check(String jobName, String jobGroup) throws Exception {
if (quartzJobService.checkExistsScheduleJob(jobName, jobGroup)) {
return "存在定时任务:" + jobName;
} else {
return "不存在定时任务:" + jobName;
}
}
/**
* 更新定时任务,写法是一样的,直接调用quartzJobService里更新的方法即可
*/
}
3、一些理解
3.1、Quartz的集群原理以及配置?
只要在application.yml文件中配置是否为开启集群即可,Quartz的集群是通过mysql表控制的,集群节点相互之间不通信,而是通过定时任务持久化加锁的方式来实现集群。
对开发人员来说,并不需要管理集群模式下的Quartz。