目录结构
SQL脚本
-- 1.1. qrtz_blob_triggers : 以Blob 类型存储的触发器。
-- 1.2. qrtz_calendars:存放日历信息, quartz可配置一个日历来指定一个时间范围。
-- 1.3. qrtz_cron_triggers:存放cron类型的触发器。
-- 1.4. qrtz_fired_triggers:存放已触发的触发器。
-- 1.5. qrtz_job_details:存放一个jobDetail信息。
-- 1.6. qrtz_job_listeners:job监听器。
-- 1.7. qrtz_locks: 存储程序的悲观锁的信息(假如使用了悲观锁)。
-- 1.8. qrtz_paused_trigger_graps:存放暂停掉的触发器。
-- 1.9. qrtz_scheduler_state:调度器状态。
-- 1.10. qrtz_simple_triggers:简单触发器的信息。
-- 1.11. qrtz_trigger_listeners:触发器监听器。
-- 1.12. qrtz_triggers:触发器的基本信息。
-- 1.13. sys_scheduler_job:自定义定时任务配置表。
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;
CREATE TABLE `sys_scheduler_job` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(100) NOT NULL COMMENT 'JOB名称',
`group_name` varchar(60) DEFAULT NULL COMMENT '组名称',
`job_class` varchar(200) DEFAULT NULL COMMENT 'JOB类名',
`cron_expression` varchar(60) DEFAULT NULL COMMENT 'CRON表达式',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`status` int(8) DEFAULT '12781001' COMMENT '状态,启用:12781001,停用:12781002',
`create_by` varchar(40) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(40) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`delete_flag` int(8) DEFAULT '12781002' COMMENT '是否逻辑删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='定时任务配置表';
pom.xml
<!-- Quartz任务调度 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
quartz.properties
# 表前缀
org.quartz.jobStore.tablePrefix = QRTZ_
# 调度实例失效间隔时间 ms
org.quartz.jobStore.clusterCheckinInterval = 8000
# 是否加入集群
org.quartz.jobStore.isClustered = true
# 实际执行时间与下一次应该执行时间之间的差值,超过这个差值就不会执行,低于这个差值就会执行
# 超狗10000(10秒)会导致MISFIRE_INSTRUCTION_DO_NOTHING不起作用
org.quartz.jobStore.misfireThreshold = 6000
# 数据库持久化
org.quartz.jobStore.txIsolationLevelReadCommitted = true
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 调度标识名,集群中每个实例都使用相同名称
org.quartz.scheduler.instanceName = ClusterQuartz
org.quartz.scheduler.instanceId = AUTO
# 实例化ThreadPool时,使用的线程类为SimpleThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# 并发个数
org.quartz.threadPool.threadCount = 10
# 优先级
org.quartz.threadPool.threadPriority = 5
SchedulerConfig
package com.yun.quartz.config;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;
@Configuration
public class SchedulerConfig {
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext applicationContext;
@Bean
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setSchedulerName("cluster_scheduler");
factory.setOverwriteExistingJobs(true);
factory.setDataSource(dataSource);
factory.setQuartzProperties(quartzProperties());
SchedulerJobFactory jobFactory = new SchedulerJobFactory();
jobFactory.setApplicationContext(applicationContext);
factory.setJobFactory(jobFactory);
factory.setStartupDelay(30);
// 设置自动启动,默认为true
// factory.setAutoStartup(true);
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("/quartz.properties"));
bean.afterPropertiesSet();
return bean.getObject();
}
}
SchedulerJobFactory
package com.yun.quartz.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
public class SchedulerJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
QuartzController
package com.yun.quartz.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yun.quartz.entity.SchedulerJobDTO;
import com.yun.quartz.entity.SchedulerJobVO;
import com.yun.quartz.entity.SchedulerModeDTO;
import com.yun.quartz.service.QuartzService;
import com.yun.utils.common.ResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/quartz")
@Api(value = "QuartzController", tags = {"Quartz接口"})
public class QuartzController {
@Autowired
private QuartzService baseService;
@ApiOperation(notes="添加JOB", value = "create")
@PostMapping(value = "/create")
public ResponseResult<?> create(@Validated @RequestBody SchedulerJobDTO scheduleJobDTO) {
baseService.create(scheduleJobDTO);
return ResponseResult.success();
}
@ApiOperation(notes="修改JOB", value = "update")
@PutMapping(value = "/update")
public ResponseResult<?> update(@Validated @RequestBody SchedulerJobDTO scheduleJobDTO) {
baseService.update(scheduleJobDTO);
return ResponseResult.success();
}
@ApiOperation(notes="删除JOB", value = "delete")
@DeleteMapping(value = "/delete")
public ResponseResult<?> delete(@RequestBody SchedulerModeDTO dto) {
baseService.delete(dto.getId());
return ResponseResult.success();
}
@ApiOperation(notes="批量删除JOB", value = "deleteBatch")
@PutMapping(value = "/deleteBatch")
public ResponseResult<?> deleteBatch(@RequestBody List<Integer> ids) {
baseService.deleteBatch(ids);
return ResponseResult.success();
}
@ApiOperation(notes="暂停JOB", value = "pause")
@PutMapping(value = "/pause")
public ResponseResult<?> pause(@RequestBody SchedulerModeDTO dto) {
baseService.pause(dto.getId());
return ResponseResult.success();
}
@ApiOperation(notes="批量暂停JOB", value = "pauseBatch")
@PutMapping(value = "/pauseBatch")
public ResponseResult<?> pauseBatch(@RequestBody List<Integer> ids) {
baseService.pauseBatch(ids);
return ResponseResult.success();
}
@ApiOperation(notes="恢复JOB", value = "resume")
@PutMapping(value = "/resume")
public ResponseResult<?> resume(@RequestBody SchedulerModeDTO dto) {
baseService.resume(dto.getId());
return ResponseResult.success();
}
@ApiOperation(notes="批量恢复JOB", value = "resumeBatch")
@PutMapping(value = "/resumeBatch")
public ResponseResult<?> resumeBatch(@RequestBody List<Integer> ids) {
baseService.resumeBatch(ids);
return ResponseResult.success();
}
@ApiOperation(notes="立即执行JOB", value = "runNow")
@PutMapping(value = "/runNow")
public ResponseResult<?> runNow(@RequestBody SchedulerModeDTO dto) {
baseService.runNow(dto.getId());
return ResponseResult.success();
}
@ApiOperation(notes="分页查询", value="searchDefault")
@PostMapping("/searchDefault")
public ResponseResult<IPage<SchedulerJobVO>> searchDefault(@RequestBody SchedulerJobDTO dto) {
return ResponseResult.success(baseService.searchDefault(dto));
}
@ApiOperation(notes="查询明细", value = "getById")
@GetMapping(value = "/getById")
public ResponseResult<?> getById(@RequestParam(value = "id") Integer id) {
return ResponseResult.success(baseService.getById(id));
}
@ApiOperation(value = "查询所有JOB")
@GetMapping(value = "/queryAllJob")
public List<Map<String, Object>> queryAllQuartzJob() {
return baseService.queryAllJob();
}
}
QuartzService
package com.yun.quartz.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yun.quartz.entity.SchedulerJobDTO;
import com.yun.quartz.entity.SchedulerJobVO;
import java.util.List;
import java.util.Map;
public interface QuartzService {
void create(SchedulerJobDTO scheduleJobDTO);
void update(SchedulerJobDTO scheduleJobDTO);
void delete(Integer id);
void deleteBatch(List<Integer> ids);
void pause(Integer id);
void pauseBatch(List<Integer> ids);
void resume(Integer id);
void resumeBatch(List<Integer> ids);
void runNow(Integer id);
SchedulerJobVO getById(Integer id);
IPage<SchedulerJobVO> searchDefault(SchedulerJobDTO dto);
List<Map<String, Object>> queryAllJob();
List<Map<String, Object>> queryRunJob();
}
QuartzServiceImpl
package com.yun.quartz.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yun.constant.CommonConstant;
import com.yun.constant.DictConstant;
import com.yun.constant.ErrorConstant;
import com.yun.mapper.SchedulerJobMapper;
import com.yun.quartz.entity.SchedulerJobDTO;
import com.yun.quartz.entity.SchedulerJobPO;
import com.yun.quartz.entity.SchedulerJobVO;
import com.yun.utils.common.BizException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.*;
/**
* <p>
* 定时任务表 服务实现类
* </p>
*
* @author CNSTT
* @since 2023-03-20
*/
@Slf4j
@Service
public class QuartzServiceImpl implements QuartzService {
@Autowired
private Scheduler scheduler;
@Autowired
private SchedulerJobMapper schedulerJobMapper;
@PostConstruct
public void startScheduler() {
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 新增JOB
*
* @param dto 传参
*/
@Override
@Transactional
public void create(SchedulerJobDTO dto) {
LambdaQueryWrapper<SchedulerJobPO> wrapper = new QueryWrapper<SchedulerJobPO>().lambda();
wrapper.eq(SchedulerJobPO::getName, dto.getName());
wrapper.eq(SchedulerJobPO::getGroupName, dto.getGroupName());
List<SchedulerJobPO> list = schedulerJobMapper.selectList(wrapper);
if (!CollectionUtils.isEmpty(list)) {
throw new BizException("任务组和名称已存在,请检查");
}
try {
// 任务名称和组构成任务key
JobDetail jobDetail = JobBuilder.newJob((Class<? extends QuartzJobBean>) Class.forName(dto.getJobClass()))
.withIdentity(dto.getName(), dto.getGroupName())
.build();
// 设置job参数
// if (jobData!= null && jobData.size() > 0) {
// jobDetail.getJobDataMap().putAll(jobData);
// }
// 触发器key
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(dto.getName(), dto.getGroupName())
.startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(dto.getCronExpression())).startNow().build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, trigger);
} catch (ClassNotFoundException e) {
e.printStackTrace();
log.error("【ERROR】定时任务类【{}】未找到==========", dto.getJobClass());
throw new BizException("定时任务类【" + dto.getJobClass() + "】未找到");
} catch (Exception e) {
e.printStackTrace();
throw new BizException("新增定时任务异常");
}
// 插入记录
SchedulerJobPO po = new SchedulerJobPO();
BeanUtils.copyProperties(dto, po);
po.setCreateBy(CommonConstant.ADMIN_USER_ID);
po.setCreateTime(LocalDateTime.now());
po.setUpdateBy(CommonConstant.ADMIN_USER_ID);
po.setUpdateTime(LocalDateTime.now());
po.setDeleteFlag(DictConstant.DICT_NO);
schedulerJobMapper.insert(po);
}
/**
* 修改JOB
*
* @param dto 传参
*/
@Override
@Transactional
public void update(SchedulerJobDTO dto) {
SchedulerJobPO po = querySchedulerById(dto.getId());
try {
TriggerKey triggerKey = TriggerKey.triggerKey(dto.getName(), dto.getGroupName());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(dto.getCronExpression())).build();
// 重启触发器
scheduler.rescheduleJob(triggerKey, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("修改定时任务异常");
}
// 修改记录
BeanUtils.copyProperties(dto, po);
po.setUpdateBy(CommonConstant.ADMIN_USER_ID);
po.setUpdateTime(LocalDateTime.now());
schedulerJobMapper.updateById(po);
}
/**
* 删除JOB
*
* @param id 主键
*/
@Override
@Transactional
public void delete(Integer id) {
SchedulerJobPO po = querySchedulerById(id);
try {
scheduler.deleteJob(new JobKey(po.getName(), po.getGroupName()));
} catch (Exception e) {
e.printStackTrace();
throw new BizException("删除定时任务异常");
}
// 删除记录
schedulerJobMapper.deleteById(id);
}
/**
* 批量删除JOB
*
* @param ids 主键集合
*/
@Override
@Transactional
public void deleteBatch(List<Integer> ids) {
ids.forEach(this::delete);
}
/**
* 暂停JOB
*
* @param id 主键
*/
@Override
@Transactional
public void pause(Integer id) {
SchedulerJobPO po = querySchedulerById(id);
try {
JobKey jobKey = JobKey.jobKey(po.getName(), po.getGroupName());
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("暂停定时任务异常");
}
// 修改记录
po.setStatus(DictConstant.DICT_NO);
po.setUpdateBy(CommonConstant.ADMIN_USER_ID);
po.setUpdateTime(LocalDateTime.now());
schedulerJobMapper.updateById(po);
}
/**
* 批量暂停JOB
*
* @param ids 主键集合
*/
@Override
@Transactional
public void pauseBatch(List<Integer> ids) {
ids.forEach(this::pause);
}
/**
* 恢复JOB
*
* @param id 主键
*/
@Override
@Transactional
public void resume(Integer id) {
SchedulerJobPO po = querySchedulerById(id);
try {
JobKey jobKey = JobKey.jobKey(po.getName(), po.getGroupName());
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("恢复定时任务异常");
}
// 修改记录
po.setStatus(DictConstant.DICT_YES);
po.setUpdateBy(CommonConstant.ADMIN_USER_ID);
po.setUpdateTime(LocalDateTime.now());
schedulerJobMapper.updateById(po);
}
/**
* 批量恢复JOB
*
* @param ids 主键集合
*/
@Override
@Transactional
public void resumeBatch(List<Integer> ids) {
ids.forEach(this::resume);
}
/**
* 立即执行JOB
*
* @param id 主键
*/
@Override
@Transactional
public void runNow(Integer id) {
SchedulerJobPO po = querySchedulerById(id);
try {
JobKey jobKey = JobKey.jobKey(po.getName(), po.getGroupName());
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("立即执行定时任务异常");
}
}
/**
* 根据ID查询定时任务
*
* @param id 主键
* @return IPage<ScheduleJobDTO>
*/
private SchedulerJobPO querySchedulerById(Integer id) {
if (id == null) throw new BizException(ErrorConstant.ERROR_MSG_KEY_MISSING);
SchedulerJobPO po = schedulerJobMapper.selectById(id);
if (po == null) throw new BizException("定时任务" + ErrorConstant.ERROR_MSG_NOT_EXISTS);
return po;
}
/**
* 根据ID查询定时任务
*
* @param id 主键
*/
@Override
public SchedulerJobVO getById(Integer id) {
SchedulerJobVO vo = new SchedulerJobVO();
SchedulerJobPO po = querySchedulerById(id);
BeanUtils.copyProperties(po, vo);
return vo;
}
/**
* 分页查询
*
* @return IPage<ScheduleJobDTO>
*/
@Override
public IPage<SchedulerJobVO> searchDefault(SchedulerJobDTO dto) {
return schedulerJobMapper.searchDefault(new Page<>(dto.getCurrentPage(), dto.getPageSize()), dto);
}
/**
* 获取所有计划中的任务列表
*
* @return List<Map<String, Object>>
*/
@Override
public List<Map<String, Object>> queryAllJob() {
List<Map<String, Object>> jobList;
try {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
jobList = new ArrayList<>();
for (JobKey jobKey : jobKeys) {
log.info("maps: {}", scheduler.getJobDetail(jobKey).getJobDataMap().getWrappedMap());
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
Map<String, Object> map = new HashMap<>();
map.put("jobName", jobKey.getName());
map.put("jobGroupName", jobKey.getGroup());
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
}
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("query all jobs error!");
}
return jobList;
}
/**
* 获取所有正在运行的job
*
* @return List<Map<String, Object>>
*/
@Override
public List<Map<String, Object>> queryRunJob() {
List<Map<String, Object>> jobList;
try {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
jobList = new ArrayList<>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
Map<String, Object> map = new HashMap<>();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
map.put("jobName", jobKey.getName());
map.put("jobGroupName", jobKey.getGroup());
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
} catch (SchedulerException e) {
e.printStackTrace();
throw new BizException("query run jobs error!");
}
return jobList;
}
}
TimerPollingCronJob
package com.yun.quartz.job;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Slf4j
@DisallowConcurrentExecution
public class TimerPollingCronJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
log.info("TimerPollingCronJob Start................");
log.info("TimerPollingCronJob End................");
}
}
SchedulerJobPO
package com.yun.quartz.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 定时任务配置表
* </p>
*
* @author CNSTT
* @since 2023-03-17
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sys_scheduler_job")
@ApiModel(value="定时任务", description="定时任务配置表")
public class SchedulerJobPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "任务名称")
@TableField(value = "name")
private String name;
@ApiModelProperty(value = "组名称")
@TableField(value = "group_name")
private String groupName;
@ApiModelProperty(value = "类名称")
@TableField(value = "job_class")
private String jobClass;
@ApiModelProperty(value = "cron表达式")
@TableField(value = "cron_expression")
private String cronExpression;
@ApiModelProperty(value = "备注")
@TableField(value = "remark")
private String remark;
@ApiModelProperty(value = "任务状态")
@TableField(value = "status")
private Integer status;
@ApiModelProperty(value = "创建人")
@TableField(value = "create_by")
private String createBy;
@ApiModelProperty(value = "创建时间")
@TableField(value = "create_time")
private LocalDateTime createTime;
@ApiModelProperty(value = "修改人")
@TableField(value = "update_by")
private String updateBy;
@ApiModelProperty(value = "修改时间")
@TableField(value = "update_time")
private LocalDateTime updateTime;
@ApiModelProperty(value = "是否逻辑删除")
@TableField(value = "delete_flag")
private Integer deleteFlag;
}
SchedulerJobDTO
package com.yun.quartz.entity;
import com.yun.entity.dto.PageDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Data
public class SchedulerJobDTO extends PageDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private Integer id;
@ApiModelProperty(value = "任务名称")
@NotNull(message = "任务名称不可为空")
private String name;
@ApiModelProperty(value = "组名称")
@NotNull(message = "组名称不可为空")
private String groupName;
@ApiModelProperty(value = "类名称")
@NotNull(message = "类名称不可为空")
private String jobClass;
@ApiModelProperty(value = "cron表达式")
@NotNull(message = "cron表达式不可为空")
private String cronExpression;
@ApiModelProperty(value = "任务状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
}
分页查询 /searchDefault
新建 /create & 编辑 /update
暂停 /pauseBatch & 恢复 /resumeBatch
删除 /deleteBatch & 立即执行 /runNow