为了账号安全,请及时绑定邮箱和手机立即绑定

Quartz调度任务学习入门:从零开始搭建任务调度系统

概述

本文将带你深入学习Quartz调度任务的基础知识,涵盖安装配置、任务创建、触发器设置以及持久化存储等内容。你将了解到如何使用Java API和XML配置文件来管理定时任务,并掌握任务的并发控制、错误处理和监控方法。通过实战演练,你将学会构建一个简单的任务调度系统,用于执行定时清理数据库的操作。Quartz调度任务学习入门,从这里开始。

Quartz简介与安装配置
Quartz是什么?

Quartz是一个开源的任务调度框架,用于在Java应用程序中实现定时任务调度。Quartz可用于执行后台任务、计划任务、定时任务等场景。Quartz提供的功能非常强大,支持灵活的任务调度、复杂的触发器设置、任务的持久化等功能。Quartz可以与各种Java应用程序结合使用,如Web应用程序、独立应用程序、EJB等。

Quartz的核心组件包括:

  • Scheduler:调度器,用于管理整个调度系统中的任务与触发器。
  • Job:任务,代表需要执行的具体逻辑。
  • Trigger:触发器,定义任务的执行条件。
  • JobStore:任务存储,存储任务和触发器信息。
  • Listener:监听器,用于监听调度器中的事件。
Quartz的安装方法

安装Quartz需要先下载Quartz的jar包。Quartz依赖于Java标准库,因此只需要将quartz-2.3.2.jar(或其他版本)添加到Java项目的类路径中即可。

Maven依赖配置

如果你的项目使用Maven构建,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
   ibli>quartz
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

Gradle依赖配置

如果你的项目使用Gradle构建,可以在build.gradle文件中添加以下依赖:

dependencies {
    implementation 'org.quartz-scheduler:quartz:2.3.2'
}

手动添加jar包

如果项目是通过IDE或其他构建工具管理的,可以直接下载quartz-2.3.2.jar文件,并将其添加到项目的类路径中。例如,对于一个Maven项目,可以将jar包放入项目的src/main/resources/lib目录下,并将该目录添加到项目的类路径中。

配置示例

Quartz可以通过配置文件(如quartz.properties)或Java API进行配置。以下是quartz.properties配置文件的一个示例:

# 指定任务存储方式
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

# 指定线程池大小
org.quartz.threadPool.threadCount = 10

# 配置调度器实例名称
org.quartz.scheduler.instanceName = MyScheduler

也可以使用Java代码进行配置:

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

public class QuartzConfigExample {
    public static void main(String[] args) throws Exception {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
    }
}
创建第一个调度任务
创建简单任务的步骤

创建一个简单的调度任务需要以下步骤:

  1. 创建一个Job类。
  2. 使用XML或Java API配置调度任务。
  3. 创建并配置Trigger
  4. JobTrigger添加到调度器中。
  5. 启动调度器。
编写任务类

Job类需要实现org.quartz.Job接口。下面是一个简单的任务类示例:

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

public class SimpleJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job is running at " + System.currentTimeMillis());
    }
}
使用XML和Java API配置调度任务

使用XML配置

在XML配置中,首先需要在quartz.properties文件中启用XML配置文件的加载:

org.quartz.properties.file.name = quartz.properties
org.quartz.jobStore.isClustered = false
org.quartz.scheduler.instanceName = MyScheduler

然后在Spring配置文件中定义任务和触发器:

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <bean class="org.springframework.scheduling.quartz.CronTriggerBean">
                <property name="jobDetail">
                    <bean class="org.springframework.scheduling.quartz.JobDetailBean">
                        <property name="jobClass" value="com.example.SimpleJob"/>
                    </bean>
                </property>
                <property name="cronExpression" value="0/5 * * * * ?"/>
            </bean>
        </list>
    </property>
</bean>

使用Java API配置

使用Java API配置调度任务更加灵活,可以直接在代码中进行配置:

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

public class JavaApiConfigExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
掌握调度任务的基础特性
调度任务的触发器设置

Quartz提供了多种类型的触发器,每种触发器有其自己的特点和用途。

  • SimpleTrigger:用于执行一次或多次的定时任务。
  • CronTrigger:用于基于Cron表达式的定时任务。
  • CalendarIntervalTrigger:用于基于指定的时间间隔的定时任务。
  • DailyTimeTrigger:用于每天固定时间执行的任务。
Cron表达式的使用

Cron表达式是一种用来描述定时任务执行时间的紧凑表示法,主要用于定义任务的执行频率。例如,0/5 * * * * ?表示任务每5秒执行一次。

Cron表达式的格式

Cron表达式由6或7个字段组成,表示秒、分钟、小时、日期、月份、星期以及年份(可选)。

秒 分钟 小时 日期 月份 星期 年份

例如,表达式0 0/5 * * * ?表示任务每5分钟执行一次。如果只需要每小时执行一次,可以使用0 0 * * * ?来表示。

Cron表达式示例

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

public class CronExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
任务的执行时间及频率设定

任务的执行时间可以通过TriggerstartTimeendTime属性设置。例如,一个任务可以从2023年1月1日开始执行,到2023年12月31日结束。

设置执行时间和频率

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

public class TimeFrequencyExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Date startTime = new Date();
        Date endTime = new Date(startTime.getTime() + 365 * 24 * 60 * 60 * 1000); // 1 year from now

        trigger = trigger.getTriggerBuilder()
            .startAt(startTime)
            .endAt(endTime)
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
调度任务的高级功能
任务的并发控制

Quartz允许用户控制任务的并发执行,这可以通过设置Job类的并发控制属性来实现。例如,如果一个任务需要确保在同一时间只有一个实例在运行,可以设置concurrentExecutionPolicyDisallowConcurrentExecution

并发控制示例

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

public class ConcurrencyExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
错误处理和任务恢复

Quartz提供了一套错误处理机制,可以在任务执行失败时采取相应的措施。例如,可以设置任务重试策略,或者在任务执行失败时发送邮件或短信通知。

错误处理示例

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

public class ErrorHandlingExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);

        JobListener listener = new JobListenerSupport("myJobListener") {
            @Override
            public void jobToBeExecuted(JobExecutionContext context) {
                System.out.println("Job is about to be executed.");
            }

            @Override
            public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
                if (jobException != null) {
                    System.out.println("Job failed: " + jobException.getMessage());
                    // 可以设置重试策略或其他错误处理措施
                }
            }
        };
        scheduler.getListenerManager().addJobListener(listener);
    }
}
调度任务的持久化

Quartz支持任务的持久化存储,这有助于任务在系统重启后仍然能够正常运行。持久化存储可以通过不同的JobStore实现,如RAMJobStore(内存存储)和 JDBCJobStore(数据库存储)。

持久化示例

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.jdbcjobstore.JobStoreTX;
import org.quartz.spi.JobStore;
import org.quartz.spi.ThreadPool;

public class PersistenceExample {
    public static void main(String[] args) throws Exception {
        JobStore jobStore = new JobStoreTX();
        ThreadPool threadPool = new org.quartz.simpl.SimpleThreadPool();

        SchedulerFactory factory = new StdSchedulerFactory();
        factory.configure(new Properties() {{
            put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
            put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
            put("org.quartz.threadPool.threadCount", "10");
            put("org.quartz.scheduler.instanceName", "MyScheduler");
        }});

        Scheduler scheduler = factory.getScheduler();
        scheduler.start();

        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        scheduler.scheduleJob(job, trigger);
    }
}
调度任务的监控与管理
实时监控任务状态

Quartz提供了多种方式来监控任务的状态,包括监听器、JMX管理和JMX MBean。

监听器示例

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

public class MonitoringExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);

        JobListener listener = new JobListenerSupport("myJobListener") {
            @Override
            public void jobToBeExecuted(JobExecutionContext context) {
                System.out.println("Job is about to be executed.");
            }

            @Override
            public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
                System.out.println("Job was executed." + (jobException != null ? " with exception: " + jobException.getMessage() : ""));
            }
        };
        scheduler.getListenerManager().addJobListener(listener);
    }
}
日志记录与错误分析

Quartz支持日志记录,可以通过配置日志框架(如Log4j、SLF4J等)来记录任务执行的日志信息。

日志记录示例

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingExample {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingExample.class);

    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);

        scheduler.getListenerManager().addJobListener(new JobListenerSupport("myJobListener") {
            @Override
            public void jobToBeExecuted(JobExecutionContext context) {
                LOGGER.info("Job is about to be executed.");
            }

            @Override
            public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
                LOGGER.info("Job was executed." + (jobException != null ? " with exception: " + jobException.getMessage() : ""));
            }
        });
    }
}
动态管理任务(添加/删除/暂停/恢复)

Quartz提供了API来动态管理任务,如添加、删除、暂停和恢复任务。

动态管理任务示例

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

public class DynamicManagementExample {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
            .withIdentity("job1", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"))
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);

        // 暂停任务
        scheduler.pauseJob(job.getKey());

        // 恢复任务
        scheduler.resumeJob(job.getKey());

        // 删除任务
        scheduler.deleteJob(job.getKey());
    }
}
实战演练:构建一个简单的任务调度系统
应用场景分析

假设我们需要构建一个任务调度系统,用于定时清理数据库中的过期数据。任务需要每天凌晨定时执行,并可以在任务执行失败时自动重试。

使用Quartz实现具体功能

创建任务类

首先,创建一个用于清理数据库的Job类:

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

public class CleanupJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Cleanup job is running at " + System.currentTimeMillis());
        // 这里可以添加清理数据库的具体逻辑
    }
}

配置调度任务

接下来,配置调度任务,使用Java API来设置任务和触发器。

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

public class CleanupScheduler {
    public static void main(String[] args) throws Exception {
        JobDetail job = JobBuilder.newJob(CleanupJob.class)
            .withIdentity("cleanupJob", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("cleanupTrigger", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?")) // 每天0点执行
            .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
构建完成后的测试与优化

测试任务执行

可以通过运行CleanupScheduler类来测试任务是否能够按照预期执行。

优化任务配置

根据实际需求,可以进一步优化任务配置,例如设置任务的并发控制策略、错误处理策略等。

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.JobStore;
import org.quartz.spi.ThreadPool;

public class OptimizedCleanupScheduler {
    public static void main(String[] args) throws Exception {
        JobStore jobStore = new JobStoreTX();
        ThreadPool threadPool = new org.quartz.simpl.SimpleThreadPool();

        SchedulerFactory factory = new StdSchedulerFactory();
        factory.configure(new Properties() {{
            put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
            put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
            put("org.quartz.threadPool.threadCount", "10");
            put("org.quartz.scheduler.instanceName", "CleanupScheduler");
        }});

        Scheduler scheduler = factory.getScheduler();
        scheduler.start();

        JobDetail job = JobBuilder.newJob(CleanupJob.class)
            .withIdentity("cleanupJob", "group1")
            .storeDurably()
            .build();

        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("cleanupTrigger", "group1")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?")) // 每天0点执行
            .build();

        scheduler.scheduleJob(job, trigger);
    }
}
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消