一. 什么是 SpringBootQuartz ?
Quartz 是一个任务调度工具包, 能够很自由的处理添加和维护基于单次 或者 cron表达式的任务.
说明: 本文档是基于 SpringBoot 2.x
二. pom.xml 引入依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
三. 关键配置类
package com.example.quartz.config;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Description:
* @Author: ZhangLuo
*/
@Configuration
public class SchedulerAutoConfiguration {
/**
* Spring提供的处理任务的线程池, 和 JDK 提供的 ThreadPoolExecutor 有所区别
* @return
*/
@Bean("executor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);//核心池大小
executor.setMaxPoolSize(100);//最大线程数
executor.setQueueCapacity(1000);//队列程度
executor.setKeepAliveSeconds(1000);//线程空闲时间
executor.setThreadNamePrefix("scheduler-");//线程前缀名称
/**
* 拒绝策略:
* AbortPolicy:用于被拒绝任务的处理程序,它将抛出RejectedExecutionException
*
* CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务。
*
* DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试execute。
*
* DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
*/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//配置拒绝策略
return executor;
}
/**
* 调度工厂
* @return
*/
@Bean(name="schedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executor") Executor executor) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setAutoStartup(true);
//这里如果不配置任务池,它就会默认加载SimpleThreadPool
factory.setTaskExecutor(executor);
return factory;
}
/**
* 调度员
* @return
*/
@Bean(name="scheduler")
public Scheduler scheduler(@Qualifier("schedulerFactory") SchedulerFactoryBean factoryBean) {
return factoryBean.getScheduler();
}
}
四. 一个简单的任务类
package com.example.quartz.job;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* @Description:
* @Author: ZhangLuo
*/
@Slf4j
public class SimpleJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.info("任务被触发...");
}
}
五. 任务调度服务接口
package com.example.quartz.service;
/**
* @Description:
* @Author: ZhangLuo
*/
public interface JobSchedulerService {
/**
* 功能描述: 添加简单任务(单次)
* 可以自定义一个任务信息对象,然后从信息对象中获取参数创建简单任务
* @param executeDate 单次任务的执行时间
*/
void addSimpleJob(Date executeDate);
/**
* 功能描述: 添加定时任务
* 可以自定义一个任务信息对象,然后从信息对象中获取参数创建定时任务
* @param cronExpression cron表达式字符串
*/
void addCronJob(String cronExpression);
/**
* 功能描述: 修改任务Trigger,即修改任务的定时机制(仅支持表达式任务)
* @param cronExpression cron表达式字符串
*/
void modifyCronJob(String cronExpression);
/**
* 功能描述: 暂停任务,只支持定时任务的暂停,不支持单次任务,单次任务需要interrupt
* @param
*/
void pauseCronJob();
/**
* 功能描述: 从暂停状态中恢复定时任务运行(仅支持表达式任务)
* @param
*/
void resumeCronJob();
/**
* 功能描述: 删除任务(单次 或 表达式任务)
* @param
*/
void deleteJob();
}
六. 服务实现类
package com.example.quartz.service.impl;
import com.example.quartz.job.SimpleJob;
import com.example.quartz.service.JobSchedulerService;
import com.example.quartz.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.Date;
/**
* @Description: 任务调度实现类
* @Author: ZhangLuo
*/
@Slf4j
@Service
public class JobSchedulerServiceImpl implements JobSchedulerService {
/**
* 任务调度员
*/
@Autowired
@Qualifier("scheduler")
private Scheduler scheduler;
/**
* 添加单次任务
*/
@Override
public void addSimpleJob(Date executeDate) {
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
.withIdentity("testJob01", "testJob")
.build();
SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("testTrigger01", "testTrigger")
.startAt(executeDate)
.build();
try {
scheduler.scheduleJob(jobDetail, simpleTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 添加循环任务
*/
@Override
public void addCronJob(String cronExpression) {
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
.withIdentity("testJob01", "testJob")
.build();
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().
withIdentity("cronTrigger01", "cronTrigger")
.withSchedule(scheduleBuilder)
.build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 修改定时任务
*/
@Override
public void modifyCronJob(String cronExpression) {
TriggerKey oldKey = new TriggerKey("cronTrigger01", "cronTrigger");
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().
withIdentity("cronTrigger01", "cronTrigger")
.withSchedule(scheduleBuilder)
.build();
try {
scheduler.rescheduleJob(oldKey, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 暂停任务
*/
@Override
public void pauseCronJob() {
JobKey jobKey = new JobKey("testJob01", "testJob");
try {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (ObjectUtils.isEmpty(jobDetail)) {
System.out.println("没有这个job");
}
} catch (SchedulerException e) {
e.printStackTrace();
}
try {
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 恢复任务运行
*/
@Override
public void resumeCronJob() {
JobKey jobKey = new JobKey("testJob01", "testJob");
try {
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 删除任务
*/
@Override
public void deleteJob() {
JobKey jobKey = new JobKey("testJob01", "testJob");
try {
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
七. 添加接口测试服务类
package com.example.quartz.controller;
import com.example.quartz.service.JobSchedulerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:
* @Author: ZhangLuo
*/
@RestController
public class QuartzController {
@Autowired
private JobSchedulerService schedulerService;
/**
* 启动单次任务
* @param dateStr
* @return
*/
@GetMapping("/simpleJob")
public String simpleJob(String dateStr) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date executeDate = null;
try {
executeDate = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
// 测试, 就不考虑异常情况了
schedulerService.addSimpleJob(executeDate);
return "ok";
}
/**
* 添加表达式任务
* @param cronExpression
* @return
*/
@GetMapping("/addCronJob")
public String addCronJob(String cronExpression) {
schedulerService.addCronJob(cronExpression);
return "ok";
}
/**
* 修改表达式任务
*/
@GetMapping("/modifyCronJob")
public String modifyCronJob(String cronExpression) {
schedulerService.modifyCronJob(cronExpression);
return "ok";
}
/**
* 暂停任务
* @return
*/
@GetMapping("/pauseCronJob")
public String pauseCronJob() {
schedulerService.pauseCronJob();
return "ok";
}
/**
* 恢复任务
* @return
*/
@GetMapping("/resumeCronJob")
public String resumeCronJob() {
schedulerService.resumeCronJob();
return "ok";
}
/**
* 删除单次任务
* @return
*/
@GetMapping("delCronJob")
public String delCronJob() {
schedulerService.deleteJob();
return "ok";
}
}
大功告成, 一切搞定, 根据服务实现类里的参数, 自定义数据库数据结构即可, 就可以应用到实际生产中了.
网友评论