Files
blog-press/docs/Web/SpringBoot/SpringBoot-Quartz.md

4.3 KiB
Raw Blame History

title, date
title date
SpringBoot Quarzt简介和使用 2026-06-08

一、基本概念

Quartz 是 Java 生态最主流的企业级作业调度框架支持简单间隔触发、Cron 表达式、持久化到数据库、集群部署。

  • Job任务 — 实现 execute()方法,写你要执行的业务逻辑
  • Trigger触发器 — 定义"什么时候执行",常用 SimpleTrigger固定间隔和 CronTriggerCron 表达式)
  • Scheduler调度器 — 把 Job + Trigger 绑定,负责启动和停止调度

二、原理

Job相当于员工只知道干活Trigger 相当于排班表决定什么时候干活Scheduler 相当于老板,统一管理 Job 和 Trigger。
Quartz内部有一个核心线程 QuartzSchedulerThread会不停的检查哪个员工需要在啥时候干活但并不是按照固定间隔轮询的方式而是计算出最近一次 Trigger 的触发时间,通过 wait()精确等待,当等待结束后,调度线程会唤醒线程池中的工作线程,执行到点的 Job。如果当前没有任何 Trigger了默认最多等待 30 秒,然后再重新扫描​。如果此时有新增/修改/删除任务了,调度线程会被 notifyAll()立即唤醒,重新计算最近的触发时间。

三、安装

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

  持久化:

spring:
  quartz:
    job-store-type: jdbc

  启用后会在数据库自动建表。

四、使用

4.1 定义Job

@Component
@DisallowConcurrentExecution   // 防止同一 Job 并发执行
public class QuartzJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) {
        // 获取任务内容
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();

        // TODO 根据任务内容执行任务
    }
}

4.2 定义Trigger

@Component
public class QuartzUtils {
    public static JobDetail buildJobDetail(Task task, JobKey jobKey) {
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("id", task.getId());
        jobDataMap.put("type", task.getType());
        jobDataMap.put("content", task.getContent());

        return JobBuilder.newJob(QuartzJob.class)
                .withIdentity(jobKey)  // 使用 id 作为唯一标识
                .usingJobData(jobDataMap)
                .build();
    }

    public static Trigger buildTrigger(Task task, JobKey jobKey) {
        Trigger trigger;
        // 判断任务类型Cron 任务或者一次性任务
        if (task.getCronExpression() != null && !task.getCronExpression().isEmpty()) {
            // 定时任务:使用 Cron 表达式
            trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobKey.getName() + "Trigger")
                    .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression()))
                    .forJob(jobKey)
                    .build();
        } else if (task.getExecuteTime() != null) {
            // 一次性任务:使用 executeTime
            trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobKey.getName() + "Trigger")
                    .startAt(task.getExecuteTime())
                    .forJob(jobKey)
                    .build();
        } else {
            // 如果没有 Cron 表达式和 executeTime任务不能调度抛出异常
            throw new CustomException("任务没有有效的 Cron 表达式或执行时间");
        }

        return trigger;
    }
}

::: tip 这里的Task可以根据实际情况定义:

@Data
public class Task {
    private Long id;
    private String type;
    private String content;
    private Date executeTime;
    private String cronExpression;
}

:::

4.3 执行Scheduler

@Resource
private Scheduler scheduler;

// 新增/更新
JobKey jobKey = new JobKey(task.getId().toString());
scheduler.scheduleJob(QuartzUtils.buildJobDetail(task, jobKey), QuartzUtils.buildTrigger(task, jobKey));

// 更新
scheduler.rescheduleJob(QuartzUtils.buildJobDetail(task, jobKey), QuartzUtils.buildTrigger(task, jobKey));

// 删除
scheduler.deleteJob(jobKey);