Quartz 中自定义Job实现方式很简单, 只需要实现Job接口并实现其execute方法即可. 将自定义job添加到调度列表时, 需将Job封装称JobDetail, 并设置job的标识符等信息. 需要特别注意的是, 当定时任务触发时, 调度器Scheduler 会获取JobDetail中关联的Job类信息, 并创建Job实例, 然后执行其execute方法. 当execute 方法执行完后, 会丢弃新创建的Job实例, 任其等待java 的垃圾回收.
1. 核心概念
- Job: 用于定义定时任务触发时的执行体, 即定时任务要处理的业务逻辑. 需要实现Job接口, 并重写execute接口
- JobDetail: 用于定义Job的基础信息, 如job的标识符, 描述等. 通常借助于JobBuilder 快速创建.
- JobBuilder: 快捷构建JobDetail 的工具类
1.1 Job 接口定义
自定义job时需要实现Job接口, 并重写job的唯一方法execute方法.
package org.quartz;
public interface Job {
void execute(JobExecutionContext context) throws JobExecutionException;
}
1.2 JobBuilder 常用API
JobBuilder 配置JobDetail属性的API采用链式编程风格, 方法前面返回均为该对象, 使用起来更方便简洁.
方法签名 | 方法描述 |
---|---|
public JobBuilder withIdentity(String name) | 设置job标识符ID, 分组名为默认DEFAULT |
public JobBuilder withIdentity(String name, String group) | 设置job标识符ID |
public JobBuilder withIdentity(JobKey jobKey) | 设置job标识符ID |
public JobBuilder withDescription(String jobDescription) | 设置job描述信息 |
public JobBuilder requestRecovery(boolean jobShouldRecover) | 设置当出现故障转移或恢复情况时, 是否重新执行job. 默认为false |
public JobBuilder storeDurably(boolean jobDurability) | 设置当没有Trigger关联job时, 是否继续持久化job. 设置为false时, 会删除job. 当执行scheduler.unscheduleJob(triggerKey)方法时会设计到这种情况 |
public JobBuilder usingJobData(String dataKey, String/Integer/… value) | 添加传递数据, 当任务触发时, 在execute方法中可以获取 |
public JobBuilder setJobData(JobDataMap newJobDataMap) | 设置传递数据 |
public JobDetail build() | 返回JobDetail 对象, 实际返回的时JobDetail对象 |
1.3 定时任务的并发性和JobDat更新传递性
- @DisallowConcurrentExecution: 默认情况下, quartz的定时任务是可以并发执行的, 也就是说如果本次定时任务调度还没有执行完(耗时比较长), 又到了下一个触发时间点, 那么会再次创建一个Job实例, 然后执行execute方法. quartz 提供了注解@DisallowConcurrentExecution, 用于禁止定时任务并发执行. 但是需要注意的是, 虽然@DisallowConcurrentExecution 注解时添加到自定义Job上的, 但是并发性时控制在JobDetail级别的. 也就是说, 如果一个Job配置了多个JobDetail, 那么多个JobDetail 之间可以并发执行, 但是单个JobDetail 不能并发执行.
- @PersistJobDataAfterExecution: 当job 正常执行没有抛出异常时, 更新Job存储在JobDataMap中数据, 以便下次触发时获取. 官方建议使用次注解时, 也同时设置@DisallowConcurrentExecution, 因为在允许并发执行的情况下, 可能到时参数不能按预期传递.
2. 自定义Job
2.1 自定义job实例
// 添加@DisallowConcurrentExecution注解后, 则表示此定时任务不能并发执行
// @DisallowConcurrentExecution
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 获取job定义
JobDetail jobDetail = context.getJobDetail();
// 获取job数据
JobDataMap jobDataMap = jobDetail.getJobDataMap();
// 获取Trigger
Trigger trigger = context.getTrigger();
//....
System.out.println(LocalDateTime.now() + "-" + getClass().getName() + "-hello");
}
}
2.2 构建JobDetail
- 每个定时任务都需要被定义(设置标识符, 描述等基本信息, 包装成JobDetial)之后才能被调度
- quartz提供了JobBuilder 来便捷地创建JobDetail
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class) // 指定job执行体
.withIdentity("hello","group1") // 设置job的唯一标识符
.withDescription("my first job") // 设置job 描述信息
.storeDurably(true) // 设置当没有Trigger关联job时是否继续存储job. 设置为false时, 会同时删除job; 默认为false
.requestRecovery(true) // 在程序恢复或故障转移时, 是否重新执行job, 默认为false
.usingJobData("author", "zongf") // 设置携带数据, 在job触发时可以获取
.usingJobData("year", "2019")
.build();
2.3 添加调度
# 添加调度任务, 根据job的名称和分组判断, 如果job已经存在时, 抛出异常
scheduler.scheduleJob(jobDetail, trigger);
# 添加调度任务, 如果job已经存在, 则覆盖更新jo
scheduler.scheduleJob(job, triggerSet, true);
来源:https://blog.csdn.net/zongf0504/article/details/89241345