一 核心类说明
Scheduler:调度器。所有的调度都是由它控制,是Quartz的大脑,所有任务都是由它来管理
Job:任务,想定时执行的事情(定义业务逻辑)
JobDetail:基于Job,进一步包装。其中关联一个Job,并为Job指定更详细的属性,比如标识等
Trigger:触发器。可以指定给某个任务,指定任务的触发机制
二 简单使用
1. 导入依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
2. 实现Job接口,重写execute方法
/**
* 工作类的具体实现,即到底要做什么事情
*/
public class HelloQuartz implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 1. 创建工作详情
JobDetail jobDetail = jobExecutionContext.getJobDetail();
// 2. 获取工作的具体信息
String jobName = jobDetail.getKey().getName();
String jobGroup = jobDetail.getKey().getGroup();
System.out.println("job执行,job:" + jobName + " group:" + jobGroup);
System.out.println(new Date());
}
/**
* 测试我们创建的job
* @param args
*/
public static void main(String[] args) {
try {
// 1. 创建一个默认的调度器
Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();
// 2. 定义一个Trigger,用来触发执行job的条件
// 使用TriggerBuilder触发构造器来构造Trigger
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
Trigger trigger = triggerBuilder.withIdentity("trigger1", "group1")// 声明身份
.startNow() // 现在开启
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) // 创建调度计划,每秒执行一次,一直重复
.endAt(new GregorianCalendar(2022, 7, 15, 16, 7, 0).getTime()) //2022年7月份结束
.build(); // 构建Trigger,前面的都是在填充条件
// 3. 定义一个JobDetail,这个是关键!!!将HelloQuartz中定义的工作详情告诉JobDetail
JobDetail job = JobBuilder.newJob(HelloQuartz.class).withIdentity("job1", "group1") //定义name/group
.build();
// 4. 将job和触发器填充到调度器中
defaultScheduler.scheduleJob(job, trigger);
// 5. 启动任务调度
defaultScheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
三 Trigger触发器
1. SimpleTrigger 简单触发器
按照一定的时间间隔(单位是毫秒)执行的任务
- 指定开始和结束时间
- 指定时间间隔、执行次数
示例:
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1) //每秒执行一次
.repeatForever())// 不限执行次数
.endAt(new GregorianCalendar(2020, 4, 7, 2, 24, 0).getTime())
.build();
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(3) // 每3分钟执行一次
.withRepeatCount(3)) // 执行次数不超过3次
.endAt(new GregorianCalendar(2020, 4, 7, 2, 24, 0).getTime())
.build();
2. CronTrigger 复杂触发器
适用于更加复杂的任务,支持类似于Linux Cron的语法
指定Cron表达式即可
示例:
// 每天10:00 - 12:00,每隔两分钟执行一次
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIndentity("t1", "g1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 10-12 * * ?"))
.build();
1. Cron表达式组成
表达式组成:“秒 分 时 日 月 星期几 [年]” ,其中"年" 是可选的,一般不指定。
- 如:"10 20 18 3 5 ?"代表"5月3日18点20分10秒,星期几不确定 "
位置 | 时间域 | 允许值 | 特殊值 |
---|---|---|---|
1 | 秒 | 0-59 | , - * / |
2 | 分钟 | 0-59 | , - * / |
3 | 小时 | 0-23 | , - * / |
4 | 日期 | 1-31 | , - * ? / L W |
5 | 月份 | 1-12 | , - * / |
6 | 星期 | 1-7 | , - * ? / L # |
7 | 年份(可选) | , - * / |
2. Cron表达式符号
表达式中可使用的特殊符号的含义如下
符号 | 语义 |
---|---|
星号(*) | 可用在所有字段中,表示对应时间域的每一个时刻,例如, 在分钟字段时,表示“每分钟” |
问号(?) | 该字符只在日期和星期字段中使用,它通常指定为“不确定值” |
减号(-) | 表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12 |
逗号(,) | 表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五 |
斜杠(/) | x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段 中表示5,20,35,50 |
井号(#) | 该字符只用在星期字段中,"4#2"代表第二个星期3,“5#4”代表第4个星期四 |
L | 该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。 |
如果L用在星期字段里,则表示星期六,等同于7 | |
L出现在星期字段里,而且在前面有一个数值x,则表示“这个月的最后一个周x”,例如,6L表示该月的最后星期五 | |
L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号 | |
W | 该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日 |
例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号 是星期二,那结果就是15号星期二;但必须注意关联的匹配日期不能够跨月 | |
LW组合 | 在日期字段可以组合使用LW,它的意思是当月的最后一个工作日 |
3. Cron表达式示例
表示式 | 说明 |
---|---|
0 0 12 * * ? | 每天12点运行 |
0 15 10 * * ? | 每天10:15运行 |
0 15 10 * * ? 2008 | 在2008年的每天10:15运行 |
0 * 14 * * ? | 每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59。 |
0 0/5 14 * * ? | 每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55。 |
0 0/5 14,18 * * ? | 每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次。 |
0 0-5 14 * * ? | 每天14:00点到14:05,每分钟运行一次。 |
0 0-5/2 14 * * ? | 每天14:00点到14:05,每2分钟运行一次。 |
0 10,44 14 ? 3 4 | 3月每周三的14:10分和14:44分,各运行一次。 |
0 15 10 ? * 2-6 | 每周一,二,三,四,五的10:15分运行一次。 |
0 15 10 15 * ? | 每月15日10:15分运行。 |
0 15 10 L * ? | 每月最后一天10:15分运行。 |
0 15 10 ? * 6L | 每月最后一个星期五10:15分运行。【此时天必须是"?"】 |
0 15 10 ? * 6L 2007-2009 | 在2007,2008,2009年每个月的最后一个星期五的10:15分运行。 |
五 SpringBoot整合Quartz
1. 项目准备
创建用于存放任务相关信息的表
CREATE TABLE `task_config` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`task_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务id',
`cron` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'cron表达式',
`class_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'job引用地址',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '描述',
`status` tinyint NOT NULL COMMENT '定时任务状态 0 停用,1启用',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
创建一个新的项目,添加依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<!--quartz和springboot的整合包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<!--mybatisPlus可以放我们更方便的操作mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!--数据库连接池框架-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
配置文件
数据源的配置:application-datasource.yml配置文件
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=true&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
username: root
password: ‘0000’
type: com.alibaba.druid.pool.DruidDataSource
mybatisPlus的配置:application-mybatis.yml配置文件
mybatis-plus:
#扫描xml的位置
mapper-locations: classpath*:/dao/*.xml
configuration:
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Spring的配置:application.yml配置文件
spring:
application:
name: schedule-server
profiles:
#配置激活配置文件,application-mybatis,application-datasource
active: datasource,mybatis
server:
port: 9000
2. Entity、dao
库表对应的实体类
@Data
@Accessors(chain = true)
@TableName("task_config")
public class TaskConfigEntity implements Serializable {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField("task_id")
private String taskId;
@TableField("cron")
private String cron;
@TableField("class_name")
private String className;
@TableField("description")
private String description;
@TableField("status")
private Integer status;
}
dao层接口
@Mapper
public interface TaskConfigDao extends BaseMapper<TaskConfigEntity> {
}
对应的xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.demo.dao.TaskConfigDao">
</mapper>
在启动类上添加注解@MapperScan,这是Mybatis的注解,可以用来替代@Mapper
@SpringBootApplication
//扫描路径
@MapperScan("com.example.demo.dao")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3. 配置定时器Quartz
调度器Scheduler依赖调度器工厂SchedulerFactoryBean;调度器工厂SchedulerFactoryBean依赖线程池Executor和任务工厂JobFactory
1. 创建并配置线程池
@Configuration
public class ExecutorConfig {
@Bean("taskExecutor")
public Executor getAsyncExecutors() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(10);
executor.setKeepAliveSeconds(5);
// 队列容量
executor.setQueueCapacity(0);
// 拒绝策略
executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exec) -> {
try {
// offer():将指定的元素插入到队列中,必要的话(队列满了)进行等待一直到指定的超时时间
if (!exec.getQueue().offer(r, 30, TimeUnit.SECONDS)) {
throw new Exception("任务等了30秒还没有进入队列中");
}
} catch (Exception e) {
e.printStackTrace();
}
});
return executor;
}
}
2.由于Quartz中底层的一个实例没有被Spring容器管理,所以我们需要创建这个示例并交给容器管理,这一步不可获缺!!!!
// Job工厂
@Component
public class JobFactory extends AdaptableJobFactory {
/**
* AutowireCapableBeanFactory接口是BeanFactory的子类,可以连接和填充那些生命周期不被Spring管理的已存在的bean实例
*/
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
/**
* 创建Job实例
*
* @param bundle
* @return
* @throws Exception
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 创建实例化对象
Object jobInstance = super.createJobInstance(bundle);
// 进行注入(使Spring管理该Bean),将jobInstance注入到Spring的ioc容器中
capableBeanFactory.autowireBean(jobInstance);
// 返回对象
return jobInstance;
}
}
3. 配置Scheduler调度器
@Configuration
public class ScheduleJobConfig {
// 线程池
@Resource(name = "taskExecutor")
private Executor taskExecutor;
/**
* 调度器工厂实例
* 通过JobFactory任务工厂创建一个调度器工厂
*
* @param jobFactory
* @return
*/
@Bean("schedulerFactory")
public SchedulerFactoryBean createFactoryBean(JobFactory jobFactory) {
// 1. new一个调度器工厂
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
// 2. 设置JobFactory任务工厂(这个spring没有自动帮我们创建,需要我们自己注册一个Bean,就是我们的上一步做的操作)
schedulerFactoryBean.setJobFactory(jobFactory);
// 3. 设置线程池
schedulerFactoryBean.setTaskExecutor(taskExecutor);
// 4. 设置overwriteExistJobs参数为true,可以通过使用外部文件的方式,修改已存活的job;否则修改将不会生效
schedulerFactoryBean.setOverwriteExistingJobs(true);
return schedulerFactoryBean;
}
/**
* 调度器实例
*
* @param schedulerFactoryBean
* @return
*/
@Bean("scheduler1")
public Scheduler getScheduler(@Qualifier("schedulerFactory") SchedulerFactoryBean schedulerFactoryBean) {
return schedulerFactoryBean.getScheduler();
}
}
4. 创建一个MyJob
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println(jobExecutionContext.getJobDetail().getKey() + "===" + new SimpleDateFormat("hh:mm:ss").format(new Date()));
}
}
4. 业务代码(Service层)
package com.example.demo.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo.dao.TaskConfigDao;
import com.example.demo.entity.TaskConfigEntity;
import lombok.extern.log4j.Log4j2;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Log4j2
public class ScheduleJobService {
@Autowired
private TaskConfigDao taskConfigDao;
@Autowired
private Scheduler scheduler;
/**
* 程序启动开始加载定时任务
*/
public void startJob(){
List<TaskConfigEntity> taskConfigEntities = taskConfigDao.selectList(
Wrappers.<TaskConfigEntity>lambdaQuery()
.eq(TaskConfigEntity::getStatus, 1));
if (taskConfigEntities == null || taskConfigEntities.size() == 0){
log.error("定时任务加载数据为空");
return;
}
for (TaskConfigEntity configEntity : taskConfigEntities) {
CronTrigger cronTrigger = null;
JobDetail jobDetail = null;
try {
cronTrigger = getCronTrigger(configEntity);
jobDetail = getJobDetail(configEntity);
scheduler.scheduleJob(jobDetail,cronTrigger);
log.info("编号:{}定时任务加载成功",configEntity.getTaskId());
}catch (Exception e){
log.error("编号:{}定时任务加载失败",configEntity.getTaskId());
}
}
try {
scheduler.start();
} catch (SchedulerException e) {
log.error("定时任务启动失败",e);
}
}
/**
* 停止任务
* @param taskId
*/
public void stopJob(String taskId) throws SchedulerException {
scheduler.pauseJob(JobKey.jobKey(taskId));
}
/**
* 恢复任务
* @param taskId
* @throws SchedulerException
*/
public void resumeJob(String taskId) throws SchedulerException {
scheduler.resumeJob(JobKey.jobKey(taskId));
}
/**
* 添加新的job
* @param taskId
* @throws SchedulerConfigException
*/
public void loadJob(String taskId) throws SchedulerConfigException {
TaskConfigEntity taskConfigEntity = taskConfigDao.selectOne(
Wrappers.<TaskConfigEntity>lambdaQuery()
.eq(TaskConfigEntity::getTaskId, taskId)
.eq(TaskConfigEntity::getStatus, 1));
if (taskConfigEntity == null){
throw new SchedulerConfigException("未找到相关Job配置");
}
try {
JobDetail jobDetail = getJobDetail(taskConfigEntity);
CronTrigger cronTrigger = getCronTrigger(taskConfigEntity);
scheduler.scheduleJob(jobDetail, cronTrigger);
} catch (Exception e) {
log.error("加载定时任务异常",e);
throw new SchedulerConfigException("加载定时任务异常", e);
}
}
public void unloadJob(String taskId) throws SchedulerException {
// 停止触发器
scheduler.pauseTrigger(TriggerKey.triggerKey(taskId));
// 卸载定时任务
scheduler.unscheduleJob(TriggerKey.triggerKey(taskId));
// 删除原来的job
scheduler.deleteJob(JobKey.jobKey(taskId));
}
/**
* 重新加载执行计划
* @throws Exception
*/
public void reload(String taskId) throws Exception {
TaskConfigEntity taskConfigEntity = taskConfigDao.selectOne(
Wrappers.<TaskConfigEntity>lambdaQuery()
.eq(TaskConfigEntity::getTaskId, taskId)
.eq(TaskConfigEntity::getStatus, 1));
String jobCode = taskConfigEntity.getTaskId();
// 获取以前的触发器
TriggerKey triggerKey = TriggerKey.triggerKey(jobCode);
// 停止触发器
scheduler.pauseTrigger(triggerKey);
// 删除触发器
scheduler.unscheduleJob(triggerKey);
// 删除原来的job
scheduler.deleteJob(JobKey.jobKey(jobCode));
JobDetail jobDetail = getJobDetail(taskConfigEntity);
CronTrigger cronTrigger = getCronTrigger(taskConfigEntity);
// 重新加载job
scheduler.scheduleJob(jobDetail, cronTrigger);
}
//组装JobDetail
private JobDetail getJobDetail(TaskConfigEntity configEntity) throws ClassNotFoundException {
Class<? extends Job> aClass = Class.forName(configEntity.getClassName()).asSubclass(Job.class);
return JobBuilder.newJob()
.withIdentity(JobKey.jobKey(configEntity.getTaskId()))
.withDescription(configEntity.getDescription())
.ofType(aClass).build();
}
//组装CronTrigger
private CronTrigger getCronTrigger(TaskConfigEntity configEntity){
CronTrigger cronTrigger = null;
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(configEntity.getCron());
cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(TriggerKey.triggerKey(configEntity.getTaskId()))
.withSchedule(cronScheduleBuilder)
.build();
return cronTrigger;
}
}
5. 创建监听器,项目启动的时候开启定时任务
package com.example.demo.listener;
import com.example.demo.service.ScheduleJobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* 监听容器启动,并开始从数据库加载定时任务
*/
@Component
public class ScheduleJobInitListener implements CommandLineRunner {
@Autowired
private ScheduleJobService jobService;
@Override
public void run(String... strings) throws Exception {
jobService.startJob();
}
}
6. 通过远程请求加载定时任务
package com.example.demo.controller;
import com.example.demo.service.ScheduleJobService;
import org.quartz.SchedulerConfigException;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ScheduleJobController {
@Autowired
private ScheduleJobService jobService;
@GetMapping("/load/{taskId}")
public String loadJob(@PathVariable("taskId") String taskId){
try {
jobService.loadJob(taskId);
} catch (SchedulerConfigException e) {
return "导入定时任务失败";
}
return "成功";
}
@GetMapping("/resume/{taskId}")
public String resumeJob(@PathVariable("taskId") String taskId){
try {
jobService.resumeJob(taskId);
}catch (SchedulerException e) {
return "恢复定时任务失败";
}
return "成功";
}
@GetMapping("/stop/{taskId}")
public String stopJob(@PathVariable("taskId") String taskId){
try {
jobService.stopJob(taskId);
}catch (SchedulerException e) {
return "暂停定时任务失败";
}
return "成功";
}
@GetMapping("/unload/{taskId}")
public String unloadJob(@PathVariable("taskId") String taskId){
try {
jobService.unloadJob(taskId);
}catch (SchedulerException e) {
return "卸载定时任务失败";
}
return "成功";
}
}
7. 测试
在数据库中插入一条定时任务
INSERT INTO `test`.`task_config` (`id`, `task_id`, `cron`, `class_name`, `description`, `status`) VALUES ('1', 'TB00001', '0 * * * * ?', 'com.example.demo.job.MyJob', '每一分钟触发一次', '1');
然后启动框架,观察控制台
六 相关api和概念
1. 相关api及常用操作
调度器Scheduler
// 1. 向调度器中加载任务
Date scheduleJob(JobDetail var1, Trigger var2) throws SchedulerException;
// 2. 开启调度器
void start() throws SchedulerException;
// 3. 通过jobKey暂停某个Job
void pauseJob(JobKey var1) throws SchedulerException;
// 4. 恢复任务
void resumeJob(JobKey var1) throws SchedulerException;
// 5. 停止触发器
void pauseTrigger(TriggerKey var1) throws SchedulerException;
// 6. 卸载Job
boolean unscheduleJob(TriggerKey var1) throws SchedulerException;
// 7. 删除Job
boolean deleteJob(JobKey var1) throws SchedulerException;
- 删除Job的操作:
- 先停止触发器
- 再卸载Job
- 然后删除Job
- 如果Job中的配置发生了变化,需要先执行删除Job的操作,然后再执行加载Job的操作
- 当调度器开启之后,直接添加job之后会自动执行
2. 概念
调度器Scheduler是核心,使用的时候往里塞JobDetail和Trigger即可
JobDetail和Trigger之间通过Jobkey相关联;实际上就是Jobkey中的name属性,可以是taskId
JobDetail下的属性:jobKey、description、name、group、jobClass(Job任务)、jobDataMap(数据)、durablity(是否持久化)、shouldRecover(是否重写)
其中jobkey又有name和group
CronTrigger中:TriggerKey和Schedule调度计划
创建方式:
// 创建触发器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(TriggerKey.triggerKey(task.getTaskId()))
.withSchedule(cronScheduleBuilder).build();
// 创建job
Class<? extends Job> taskConfigEntityJobClass = Class.forName(task.getClassName()).asSubclass(Job.class);
JobDetail jobDetail = JobBuilder.newJob(taskConfigEntityJobClass)
.withIdentity(JobKey.jobKey(task.getTaskId()))
.withDescription(task.getDescription())
// .ofType(taskConfigEntityJobClass)
.build();
开启方式:
// 加载到调度器中
scheduler.scheduleJob(jobDetail, trigger);
// 开启
scheduler.start();
可参考:
- https://segmentfault.com/a/1190000039073805
- https://cloud.tencent.com/developer/article/1640190