Quartz 是一个功能强大、开源、且特性丰富的作业调度库。它几乎可以用在任何的 Java 应用程序中,从微小的独立应用到大型的商业系统。Quartz 允许开发者根据时间间隔或特定时间点来调度作业(任务)的执行。
1.核心概念
调度器(Scheduler):这是整个系统的控制中心,是 Quartz 的大脑。开发者通过 Scheduler 的API来与框架交互,用于安排、执行、暂停、删除作业等。
作业(Job):这是一个接口,你需要实现它来定义你想要执行的任务。你创建一个类,实现 org.quartz.Job 接口,并重写 execute(JobExecutionContext context) 方法。你的业务逻辑就写在这个方法里。
触发器(Trigger):它定义何时执行作业。一个Job可以被多个Trigger触发,一个Trigger只能关联一个Job。
JobDetail :它用于定义Job的实例,包含了Job实体类以及各种静态属性。
2.常见应用场景
报表生成:每天凌晨生成前一天的报表、用户行为报告等。
自动化任务:在非高峰时执行数据备份、缓存预热等重量级任务。
数据同步/清理:定时从A系统同步到B系统,或定时清理数据库中的过期日志、临时数据。
邮件/消息推送:定时向用户发送生日祝福、新闻简报、促销活动通知。
系统监控与检查:每隔一段时间检查系统健康情况、服务是否可用、磁盘空间是否不足等。
3.导入Quartz依赖
<!-- 版本号可能有更新,请查看最新版本 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
4.需要执行的作业
方法内部写自己需要执行的业务逻辑。
@Slf4j
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("Cron定时任务执行开始:" + new Date());
log.info("Cron定时任务执行结束:" + new Date());
}
}
5.使用触发器、调度器来执行作业
这里是根据 SysJob 表数据来决定每天的特定时间执行(数据只有一条)。
这里将时间改成了Cron表达式,如果想改成每周或者每月需要修改 getCronExpression 方法。
@Slf4j
public class DailyScheduledTask {
// 获取调度器
private static Scheduler scheduler = null;
private static Map<Long, JobKey> map = new ConcurrentHashMap<>();
public static void addCron(SysJob sysJob) {
try {
// 获取调度器
scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义任务
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
// 使用Cron表达式设置每天的特定时间点
String cronExpression = getCronExpression(sysJob.getCronTime());
// 定义触发器,使用Cron表达式
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
// 将任务和触发器注册到调度器
scheduler.scheduleJob(job, trigger);
log.info("addCron的trigger:"+ JSON.toJSONString(trigger.getJobKey()));
map.put(sysJob.getId(),trigger.getJobKey());
// 启动调度器
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
// 删除定时任务
public static void removeCron(Long id) {
try {
if (scheduler != null) {
if (CollectionUtils.isNotEmpty(map)) {
log.info("removeCron的trigger:"+ JSON.toJSONString(map.get(id)));
scheduler.deleteJob(map.get(id));
}
}
}catch (SchedulerException e) {
e.printStackTrace();
}
}
// 使用Cron表达式设置每天的特定时间点
private static String getCronExpression(Date executionTime) {
SimpleDateFormat dateFormat = new SimpleDateFormat("ss mm HH");
return dateFormat.format(executionTime) + " * * ?";
}
}
6.SysJob 表结构
public class SysJob {
private Long id; //主键
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date cronTime; //定时时间
private Integer status; //状态:0-未启用,1-启用
private Long createId;
private Date createTime;
private Long updateId;
private Date updateTime;
}
7.使用(修改表数据时,删除任务重新添加,修改任务时间)
@PostMapping("/updateCron")
public Result<?> updateCron(@RequestBody SysJob sysJob) {
// 删除原本的任务
SysJob byId = sysJobService.getById(sysJob.getId());
if (1 == byId.getStatus()) {
DailyScheduledTask.removeCron(sysJob.getId());
}
sysJob.setUpdateId(ThreadCache.get().getUserId());
sysJob.setUpdateTime(new Date());
boolean update = sysJobService.update(sysJob, Wrappers.<SysJob>lambdaQuery().eq(SysJob::getId, sysJob.getId()));
// 修改成功:重新设定新的任务
if (update) {
Integer status = sysJob.getStatus();
if (1 == status) {
DailyScheduledTask.addCron(sysJob,jobDTO);
}
}
return Result.success("");
}
221

被折叠的 条评论
为什么被折叠?



