0.添加表
1.pom文件
<!--SpringBoot集成QuartZ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2.配置文件
server.port=8080
#====================数据源配置===================
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mall?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=zsq2170
# 使用druid数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#驱动com.mysql.cj.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#连接池初始化数量
spring.datasource.druid.initial-size=5
#最小空闲连接数
spring.datasource.druid.min-idle=10
#最大连接数
spring.datasource.druid.max-active=2000
#获取连接等待超时时间
spring.datasource.druid.max-wait=60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
spring.datasource.druid.time-between-eviction-runs-millis=60000
#=====================quartz任务配置=============================
# quartz任务存储类型:jdbc或memory
spring.quartz.job-store-type=jdbc
# 关闭是等待任务完成
spring.quartz.wait-for-jobs-to-complete-on-shutdown=true
# 可以覆盖已有的任务
spring.quartz.overwrite-existing-jobs=true
# 调度器实例名称
spring.quartz.properties.org.quartz.scheduler.instanceName=scheduler
# 调度器实例ID自动生成
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
# 调度信息存储处理类
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 使用完全兼容JDBC的驱动
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# quartz相关表前缀
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
# 是否将JobDataMap中的属性转为字符串存储
spring.quartz.properties.org.quartz.jobStore.useProperties=false
# 指定线程池实现类,对调度器提供固定大小的线程池
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# 设置并发线程数量
spring.quartz.properties.org.quartz.threadPool.threadCount=10
# 指定线程优先级
spring.quartz.properties.org.quartz.threadPool.threadPriority=5
# 配置重启任务后不执行暂停期间的任务
# 这个时间大于10000(10秒)会导致MISFIRE_INSTRUCTION_DO_NOTHING不起作用。
spring.quartz.properties.org.quartz.jobStore.misfireThreshold = 1000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
spring.datasource.druid.max-evictable-idle-time-millis=900000
# 配置检测连接是否有效
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
3.创建任务操作接口类 ScheduleService
public interface ScheduleService {
/**
* 通过CRON表达式调度任务
*/
String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data);
/**
* 通过CRON表达式调度任务 ,设置结束时间
*/
String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data,Date endDate);
/**
* 通过CRON表达式调度任务,设置开始和结束时间
*/
String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data,Date startDate,Date endDate);
/**
* 调度指定时间的任务
*/
String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data);
/**
* 取消定时任务
*/
Boolean cancelScheduleJob(String jobName);
/**
* 暂停定时任务
*/
Boolean pauseJob(String jobName);
/**
* 重启定时任务
*/
Boolean resumeJob(String jobName);
}
4.任务操作实现类 ScheduleServiceImpl
@Slf4j
@Service
public class ScheduleServiceImpl implements ScheduleService {
@Autowired
private Scheduler scheduler;
private String defaultGroup = "default_group"; //任务组
@Override
public String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data) {
return scheduleJob(jobBeanClass,cron,data,new Date(),null);
}
/**
* 通过CRON表达式调度任务 ,设置结束时间
*/
@Override
public String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data, Date endDate) {
return scheduleJob(jobBeanClass,cron,data,new Date(),endDate);
}
/**
* 通过CRON表达式调度任务,设置开始和结束时间
*/
@Override
public String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data, Date startDate, Date endDate) {
// 创建需要执行的任务
String jobName = UUID.fastUUID().toString().replaceAll("-","");
JobDetail jobDetail = JobBuilder.newJob(jobBeanClass)
.withIdentity(jobName, defaultGroup)
.usingJobData("data", data)
.build();
//创建触发器,指定任务执行时间
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(jobName, defaultGroup)
.startAt(startDate)
.endAt(endDate)
.withSchedule(CronScheduleBuilder.cronSchedule(cron)
.withMisfireHandlingInstructionDoNothing()) //添加此配置 ,重启不执行之前暂停期间该 执行的任务
.build();
//使用调度器进行任务调度
try {
scheduler.scheduleJob(jobDetail, cronTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
log.info("创建定时任务失败!");
}
return jobName;
}
@Override
public String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data) {
//日期转CRON表达式
String startCron = String.format("%d %d %d %d %d ? %d",
DateUtil.second(startTime),
DateUtil.minute(startTime),
DateUtil.hour(startTime, true),
DateUtil.dayOfMonth(startTime),
DateUtil.month(startTime) + 1,
DateUtil.year(startTime));
return scheduleJob(jobBeanClass, startCron, data);
}
@Override
public Boolean cancelScheduleJob(String jobName) {
boolean success = false;
try {
// 暂停触发器
scheduler.pauseTrigger(new TriggerKey(jobName, defaultGroup));
// 移除触发器中的任务
scheduler.unscheduleJob(new TriggerKey(jobName, defaultGroup));
// 删除任务
scheduler.deleteJob(new JobKey(jobName, defaultGroup));
success = true;
} catch (SchedulerException e) {
e.printStackTrace();
}
return success;
}
/**
* 暂停定时任务
*/
@Override
public Boolean pauseJob(String jobName) {
boolean success = false;
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName,defaultGroup));
success = true;
}catch (SchedulerException e){
e.printStackTrace();
}
return success;
}
/**
* 重启定时任务
*/
@Override
public Boolean resumeJob(String jobName) {
boolean success = false;
try {
scheduler.resumeTrigger(TriggerKey.triggerKey(jobName,defaultGroup));
success = true;
}catch (SchedulerException e){
e.printStackTrace();
}
return success;
}
}
5.添加发送邮件和发送短信和CRON表达式任务类继承 QuartzJobBean 或者实现Job接口都行
/**
* 发送邮件定时任务执行器
* Created by macro on 2020/9/27.
*/
@Slf4j
@Component
public class SendEmailJob extends QuartzJobBean {
@Autowired
private ScheduleService scheduleService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Trigger trigger = jobExecutionContext.getTrigger();
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String data = jobDataMap.getString("data");
log.info("定时发送邮件操作:{}",data);
//完成后删除触发器和任务
scheduleService.cancelScheduleJob(trigger.getKey().getName());
}
}
@Slf4j
@Component
public class SendEmailJob extends QuartzJobBean {
@Autowired
private ScheduleService scheduleService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Trigger trigger = jobExecutionContext.getTrigger();
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String data = jobDataMap.getString("data");
log.info("定时发送邮件操作:{}",data);
//完成后删除触发器和任务
scheduleService.cancelScheduleJob(trigger.getKey().getName());
}
}
/**
* 使用CRON表达式的任务执行器
* Created by macro on 2020/9/29.
*/
@Slf4j
@Component
public class CronProcessJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String data = jobDataMap.getString("data");
log.info("CRON表达式任务执行:{}",data);
}
}
6.添加Controller,测试任务
/**
* 定时任务调度相关接口
* Created by macro on 2020/9/29.
*/
@Api(tags = "ScheduleController", description = "定时任务调度相关接口")
@RestController
@RequestMapping("/schedule")
public class ScheduleController {
@Autowired
private ScheduleService scheduleService;
@ApiOperation("定时发送邮件")
@PostMapping("/sendEmail")
public CommonResult sendEmail(@RequestParam String startTime, @RequestParam String data) {
Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT);
String jobName = scheduleService.scheduleFixTimeJob(SendEmailJob.class, date, data);
return CommonResult.success(jobName);
}
@ApiOperation("定时发送站内信")
@PostMapping("/sendMessage")
public CommonResult sendMessage(@RequestParam String startTime, @RequestParam String data) {
Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT);
String jobName = scheduleService.scheduleFixTimeJob(SendMessageJob.class, date, data);
return CommonResult.success(jobName);
}
@ApiOperation("通过CRON表达式调度任务")
@PostMapping("/scheduleJob")
public CommonResult scheduleJob(@RequestParam String cron, @RequestParam String data) {
String jobName = scheduleService.scheduleJob(CronProcessJob.class, cron, data);
return CommonResult.success(jobName);
}
@ApiOperation("取消定时任务")
@PostMapping("/cancelScheduleJob")
public CommonResult cancelScheduleJob(@RequestParam String jobName) {
Boolean success = scheduleService.cancelScheduleJob(jobName);
return CommonResult.success(success);
}
@ApiOperation("暂停定时任务")
@PostMapping("/pauseJob")
public CommonResult pauseJob(@RequestParam String jobName) {
Boolean success = scheduleService.pauseJob(jobName);
return CommonResult.success(success);
}
@ApiOperation("重启定时任务")
@PostMapping("/resumeJob")
public CommonResult resumeJob(@RequestParam String jobName) {
Boolean success = scheduleService.resumeJob(jobName);
return CommonResult.success(success);
}
}
7.测试效果
8.配置暂停重启, 暂停之后重启,会默认执行暂停期间该执行但丢失的任务,如下图
需要配置不执行暂停期间的任务,需要加配置如下
1.配置文件添加配置
# 配置重启任务后不执行暂停期间的任务
# 这个时间大于10000(10秒)会导致MISFIRE_INSTRUCTION_DO_NOTHING不起作用。
spring.quartz.properties.org.quartz.jobStore.misfireThreshold = 1000
2.创建任务时,设置类型