Quartz 调度框架:Java 任务调度基石

FreeGuideOnline 最新 2026-06-30

java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 在这里编写任务逻辑,例如发送邮件、生成报表等 System.out.println("任务执行中..."); } }


### 2. 触发器(Trigger)
触发器决定了任务“何时”执行。Quartz 提供了两种最常用的触发器:
- **SimpleTrigger**:适合固定间隔、重复次数的场景(如每 30 秒运行一次,共 10 次)。
- **CronTrigger**:基于 Cron 表达式定义复杂的调度规则,如“每天上午 9:15”或“每周一至周五 18:00”。

### 3. 调度器(Scheduler)
`Scheduler` 是 Quartz 的心脏,负责将 Job 和 Trigger 组织在一起并启动执行。你可以通过 `SchedulerFactory` 创建 `Scheduler` 实例。一个应用通常只有一个调度器实例(集群模式下为每个节点一个)。

## 快速入门:搭建你的第一个调度任务

### 环境准备
在 Maven 项目 `pom.xml` 中添加 Quartz 依赖:
```xml
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

步骤 1:创建 Job 类

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Hello Quartz! 当前时间: " + new Date());
    }
}

步骤 2:编写调度程序

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzExample {
    public static void main(String[] args) throws SchedulerException {
        // 1. 创建 Scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2. 定义 JobDetail,关联我们的 HelloJob 类
        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("helloJob", "group1")
                .build();

        // 3. 创建 SimpleTrigger:立即启动,每 3 秒执行一次,重复 forever
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("simpleTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever())
                .build();

        // 4. 将 Job 和 Trigger 注册到调度器
        scheduler.scheduleJob(job, trigger);

        // 5. 启动调度器
        scheduler.start();

        // 保持主线程存活一段时间,便于观察任务执行
        Thread.sleep(20000);
        scheduler.shutdown();
    }
}

运行程序即可看到控制台每 3 秒打印一次问候语。

CronTrigger 与 Cron 表达式

CronTrigger 是 Quzrtz 中最强大的触发器,它使用 Cron 表达式来精确定义执行时间。

一个 Cron 表达式由 7 个字段组成(最后一个年份可选):
秒 分 时 日 月 星期 [年]

常见示例:

表达式 含义
0 15 10 * * ? 每天上午 10:15 执行
0 0/5 14 * * ? 每天下午 2:00 开始,每隔 5 分钟执行一次
0 30 9 ? * MON-FRI 每周一到周五上午 9:30 执行
0 0 12 L * ? 每月最后一天中午 12:00 执行

使用 CronTrigger 的代码片段:

Trigger cronTrigger = TriggerBuilder.newTrigger()
        .withIdentity("cronTrigger", "group1")
        .withSchedule(CronScheduleBuilder.cronSchedule("0 0/1 * * * ?")) // 每分钟一次
        .build();

任务状态与持久化

默认情况下,Quartz 将任务和触发器存储在内存中(RAMJobStore),应用重启后所有调度信息会丢失。生产环境通常需要将调度信息持久化到数据库。

配置 JDBCJobStore

  1. 准备 Quartz 官方提供的数据库建表脚本(通常位于 Quartz 发行版的 docs/dbTables 目录下,选择对应数据库脚本执行)。
  2. 配置 quartz.properties
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.dataSource.myDS.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/quartz_db
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = your_password
org.quartz.dataSource.myDS.maxConnections = 5

这样,所有 Job 和 Trigger 信息都会写入数据库,应用重启后调度器会从数据库恢复之前的调度状态。

集群部署与高可用

Quartz 支持集群模式,多个节点共享一个数据库。只需配置相同的 quartz.properties 并设置集群相关选项:

org.quartz.jobStore.isClustered = true
org.quartz.scheduler.instanceId = AUTO

集群中的每个节点必须拥有唯一的 instanceId。通过数据库锁机制,集群保证同一个任务同一时间只由一个节点执行,从而实现故障转移和负载均衡。注意:所有节点需要保持时钟同步,且必须使用 JDBCJobStore。

高级特性:任务传参与监听器

传递参数给 Job

使用 JobDataMap 可以在定义 JobDetail 时传入参数,在 execute 方法中获取。

JobDetail job = JobBuilder.newJob(MyJob.class)
        .usingJobData("url", "https://example.com")
        .usingJobData("count", 10)
        .build();

// 在 execute 方法中获取
public void execute(JobExecutionContext context) {
    JobDataMap dataMap = context.getJobDetail().getJobDataMap();
    String url = dataMap.getString("url");
    int count = dataMap.getInt("count");
}

任务监听器(JobListener)

可以编写监听器来监听任务执行前后的生命周期事件。

public class MyJobListener implements JobListener {
    @Override
    public String getName() { return "myListener"; }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        System.out.println("任务即将执行: " + context.getJobDetail().getKey());
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        System.out.println("任务执行完毕");
    }
}

注册监听器到调度器:

scheduler.getListenerManager().addJobListener(new MyJobListener());