Quartz 是一个开源的作业调度框架,它产生的主要目的是为了解决企业级应用中复杂的任务调度问题。 在实际的业务场景中,常常需要按照特定的时间规则(如每天凌晨执行数据备份、每月初生成报表等)来执行各种任务,手动管理这些任务的调度不仅繁琐且容易出错。 Quartz 提供了一种灵活、可靠的方式来定义和管理这些任务的执行时间和顺序,使得开发者可以将更多的精力放在业务逻辑的实现上,而不是任务调度的细节。
Quartz 在“灵活性”、“可靠性” 和 “扩展性” 上有着优势,但是其在持久化方面的较为复杂,涉及的数据库表较多,对于一些轻量级的场景并不是很适合,本项目将提供一个超轻量的持久化方案、支持动态调用,并对 Quartz 的核心组件(Scheduler、Job、Trigger、JobDetial)进行了二次链式封装,降低了调度任务编写配置的复杂度。下面我们将以 “Quartzd” 来代指该项目。
一定要看这个demo类:src/main/java/com/quartzd/demo/DemoQuartzJob.java
在 Quartzd 中开发者编写作业调度开发者只需继承 QuartzJob 类并实现 doJob() 方法即可。
// 任务执行逻辑
public class DemoQuartzJob extends QuartzJob {
@Override
public Object doJob(JobExecutionContext context) {
return "DemoQuartzJob 执行完成";
}
}结合上下两个方案,我们可以看出,相比于使用 Quartz 和核心组件创建任务实例要简便的多的多。在 Quartzd 中我们通过 QuartzConfigFactory 去构建出 QuartzConfig(调度配置),基于 QuartzClient 去创建任务任务实例即可。
public static void main(String[] args) {
// 配置
QuartzConfig jobConfig = new QuartzConfigFactory()
.identity("12345678987654")
.setJobClass(DemoQuartzJob.class)
.cron("*/10 * * * * ?")
.build();
// 启动
new QuartzClient().create(jobConfig);
}通过 “如何启动作业调度” 我演示了如何启动作业调度,但是在实际的使用中,我们并不会如此创建,在 Quartzd 中提供了操作的 web api,如下:
@RestController
@RequestMapping("/job")
public class JobController {
private final QuartzClient quartzClient;
private final QuartzInfoService quartzInfoService;
public JobController(QuartzClient quartzClient, QuartzInfoService quartzInfoService) {
this.quartzClient = quartzClient;
this.quartzInfoService = quartzInfoService;
}
@PostMapping("/add")
public Object add(@RequestBody JobInfo jobInfo) {
jobInfo.setId(Func.uuid());
return quartzInfoService.save(jobInfo);
}
@PostMapping("/update")
public Object update(@RequestBody JobInfo jobInfo) {
JobInfo job = quartzInfoService.getById(jobInfo.getId());
if (job == null) {
throw new RuntimeException("任务实例不存在");
}
if (job.getStatus() == 1) {
throw new RuntimeException("任务实例运行中,请先关闭实例");
}
return quartzInfoService.updateById(jobInfo);
}
@GetMapping("/updateCron")
public Object updateCron(@RequestParam String id, @RequestParam String cron) {
JobInfo job = quartzInfoService.getById(id);
if (job == null) {
throw new RuntimeException("任务实例不存在");
}
if (job.getStatus() == 1) {
throw new RuntimeException("任务实例运行中,请先关闭实例");
}
if (cron.equals(job.getCron())) {
return true;
}
job.setCron(cron);
return quartzInfoService.updateById(job);
}
@GetMapping("/delete")
public Object delete(@RequestParam String id) throws ClassNotFoundException {
JobInfo jobInfo = quartzInfoService.getById(id);
if (jobInfo == null) {
return true;
}
if (jobInfo.getStatus() == 1) {
quartzClient.remove(JobInit.buildConfig(jobInfo));
}
return quartzInfoService.removeById(id);
}
@GetMapping("/start")
public Object start(@RequestParam String id) throws ClassNotFoundException {
JobInfo jobInfo = quartzInfoService.getById(id);
if (jobInfo == null) {
throw new RuntimeException("任务实例不存在");
}
if (jobInfo.getStatus() == 1) {
return true;
}
quartzClient.create(JobInit.buildConfig(jobInfo));
return true;
}
@GetMapping("/stop")
public Object stop(@RequestParam String id) throws ClassNotFoundException {
JobInfo jobInfo = quartzInfoService.getById(id);
if (jobInfo == null) {
throw new RuntimeException("任务实例不存在");
}
if (jobInfo.getStatus() == 0) {
return true;
}
quartzClient.remove(JobInit.buildConfig(jobInfo));
return true;
}
}Quartzd 并为提供前端界面,需要开发者自行设计。
CREATE TABLE `quartz_job_info` (
`id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务身份唯一标识',
`cron` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'cron',
`job_class` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'job类路径',
`data_map` text COLLATE utf8mb4_general_ci COMMENT '执行参数',
`last_time` datetime DEFAULT NULL COMMENT '最新时间',
`status` int DEFAULT NULL COMMENT '状态(0停止 1启动)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='quartz定时任务状态';id : 主键,默认使用UUID。 cron:作业调度的Cron。 job_class:继承了 QuartzJob 的类的全类名。 data_map:数据格式为 JSON 字符串,作为执行方法中的变量去使用。
config.core.com.hxh.quartzd.QuartzConfigFactory 是 Quartzd 中的一个核心类,其目的是创建 QuartzConfig,在 Quartzd 中,任务是基于 QuartzConfig 创建的。
# 下面是QuartzConfigFactory的完整使用
QuartzConfig config= new QuartzConfigFactory()
// 设置唯一标识
.identity("12345678987654")
// 设置自定义doJob类
.setJobClass(DemoQuartzJob.class)
// 可以再自定义job中取到在此传递的值,value使用json字符串
.putDataMap(JobConst.DATA_MAP_KEY, "{code: \"12345678765\"}")
// 设置cron表达式,也可以使用once()标识执行一次
.cron("*/10 * * * * ?")
// 构建config
.build(); client.core.com.hxh.quartzd.QuartzClient是 Quartzd 中另一个核心类,其作用是提供操作作业调度的 API,例如:创建、移除、更新、安全 / 强制执行一次
QuartzConfig config = ...
# 创建
quartzClient.create(config);
# 移除
quartzClient.remove(config);
# 更新
config.setCron("*/15 * * * * ?");
quartzClient.updateCron(config);
# 安全执行一次
quartzClient.createOnce(config, false);
# 强制执行一次
quartzClient.createOnce(config, true);