Quartz可以对job进行简单控制,但不支持分布式,也没有管理界面和任务分片,但使用起来比较简易。
我们开始简单使用一下,首先创建Demo,在pom文件中加入以下依赖。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.0.RELEASEversion>
<relativePath />
parent>
<dependencies>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.83version>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.5.6version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.6.3version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>dynamic-datasource-spring-boot-starterartifactId>
<version>2.5.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.19version>
dependency>
dependencies>
application.yml如下。
server:
port: 8090
# servlet:
# context-path: /
logging:
level:
root: info
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/quartz?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&useSSL=false&allowMultiQueries=true
username: root
password: 123456
# driver-class-name: com.mysql.jdbc.Driver
# 时间格式
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
quartz:
job-store-type: jdbc
initialize-schema: embedded
#设置自动启动,默认为 true
auto-startup: true
#启动时更新己存在的Job
overwrite-existing-jobs: true
properties:
org:
quartz:
scheduler:
instanceName: MyScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
misfireThreshold: 60000
clusterCheckinInterval: 10000
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 50
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
然后创建一个非常简单的Scheduler调度工厂。
@Configuration
public class QuartzConfiguration {
/**
* 注册调度器创建工厂
*/
@Bean
public Scheduler schedulerFactoryBean() throws Exception {
return StdSchedulerFactory.getDefaultScheduler();
}
}
添加两个Job Detail,我们要达到的效果是先执行完Job1再执行Job2
。两个Job都需要实现Job接口的execute方法,在其中编写业务代码。
@Slf4j
public class TestJob1 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("job1被执行,当前时间:" + new Date());
}
}
@Slf4j
public class TestJob2 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("job2被执行,当前时间:" + new Date());
}
}
然后是MVC的分层,这里只写出实现层的代码。
@Slf4j
@RequiredArgsConstructor
@Service
public class ServiceImpl implements IService {
final Scheduler scheduler;
@Override
public String addTask() throws SchedulerException {
//创建计划链表
JobChainingJobListener listener = new JobChainingJobListener("JobLink");
JobDetail job1 = JobBuilder.newJob(TestJob1.class)
.withIdentity("job1", "jg1")
.build();
JobDetail job2 = JobBuilder.newJob(TestJob2.class)
.withIdentity("job2", "jg1")
// 持久存放设置为true,不然Job2只会执行一遍
.storeDurably(true)
.build();
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "tg1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.startNow()
.build();
scheduler.addJob(job2, false, true);
//设置执行顺序为先执行Job1再执行Job2
listener.addJobChainLink(job1.getKey(), job2.getKey());
//调度器使用计划链表
scheduler.getListenerManager().addJobListener(listener);
//安排调度作业
scheduler.scheduleJob(job1, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
return "success";
}
}
这样启动项目后,请求对应的接口,就可以运行起来了。
1、首先需要创建数据库表。在官网[http://www.quartz-scheduler.org/downloads/]下载项目示例后(我是用的quartz-2.3.0-SNAPSHOT),可以在org.quartz.impl.jdbcjobstore包下找到对应数据库的创建语句。
2、增加更多的接口,这里展示对应的实现类。
// 创建一个cron的任务
@Override
public void addJob(String clazzName, String jobName, String groupName, String cronExp, Map<String, Object> param) {
try {
// 启动调度器,默认初始化的时候已经启动
scheduler.start();
//构建job信息
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(clazzName);
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, groupName).build();
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName).withSchedule(scheduleBuilder).build();
//获得JobDataMap,写入数据
if (param != null) {
trigger.getJobDataMap().putAll(param);
}
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
log.error("创建任务失败", e);
}
}
// 暂停任务
@Override
public void pauseJob(String jobName, String groupName) {
try {
scheduler.pauseJob(JobKey.jobKey(jobName, groupName));
} catch (SchedulerException e) {
log.error("暂停任务失败", e);
}
}
// 恢复任务
@Override
public void resumeJob(String jobName, String groupName) {
try {
scheduler.resumeJob(JobKey.jobKey(jobName, groupName));
} catch (SchedulerException e) {
log.error("恢复任务失败", e);
}
}
// 启动一次
@Override
public void runOnce(String jobName, String groupName) {
try {
scheduler.triggerJob(JobKey.jobKey(jobName, groupName));
} catch (SchedulerException e) {
log.error("立即运行一次定时任务失败", e);
}
}
// 更新单个任务
@Override
public void updateJob(String jobName, String groupName, String cronExp, Map<String, Object> param) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (cronExp != null) {
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
}
//修改map
if (param != null) {
trigger.getJobDataMap().putAll(param);
}
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
} catch (Exception e) {
log.error("更新任务失败", e);
}
}
// 删除单个任务
@Override
public void deleteJob(String jobName, String groupName) {
try {
//暂停、移除、删除
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, groupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, groupName));
scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
} catch (Exception e) {
log.error("删除任务失败", e);
}
}
// 开启所有的任务
@Override
public void startAllJobs() {
try {
scheduler.start();
} catch (Exception e) {
log.error("开启所有的任务失败", e);
}
}
// 暂停所有任务
@Override
public void pauseAllJobs() {
try {
scheduler.pauseAll();
} catch (Exception e) {
log.error("暂停所有任务失败", e);
}
}
// 恢复所有任务
@Override
public void resumeAllJobs() {
try {
scheduler.resumeAll();
} catch (Exception e) {
log.error("恢复所有任务失败", e);
}
}
// 关闭所有的任务
@Override
public void shutdownAllJobs() {
try {
if (!scheduler.isShutdown()) {
// 需谨慎操作关闭scheduler容器
// scheduler生命周期结束,无法再 start() 启动scheduler
scheduler.shutdown(true);
}
} catch (Exception e) {
log.error("关闭所有的任务失败", e);
}
}
需要完整Demo可以在此处下载:https://download.csdn.net/download/qq_40579464/87603431