Skip to content

Quartz 定时任务集成指南 ​

简介 ​

Quartz 是一个功能强大的开源任务调度库,广泛应用于 Java 应用程序中以实现定时任务。然而,原生的 Quartz 由于其复杂性,可能会增加开发和维护的难度。为了简化这一过程,本文将介绍如何使用 tio-utils 对 Quartz 进行封装,从而提升开发效率和项目的可维护性。

Quartz 概述 ​

Quartz 是一个开放源代码的作业调度库,可以在 Java 应用程序中轻松地调度作业(任务)。它支持各种复杂的调度需求,包括基于时间的触发器、重复任务、持久化任务等。尽管功能强大,但直接使用 Quartz 可能涉及较多的配置和代码编写,因此封装 Quartz 的工具类成为必要的优化手段。

集成 Quartz 的工具类 ​

为了简化 Quartz 的使用,tio-utils 提供了以下主要工具类:

  • nexus.io.tio.utils.quartz.QuartzUtils:用于管理 Quartz 的启动、停止以及任务的调度。
  • nexus.io.tio.utils.quartz.AbstractJobWithLog:一个抽象的作业类,集成了日志记录功能,便于创建具体的定时任务。

通过这些工具类,开发者可以更加便捷地创建和管理定时任务,减少重复代码和配置的复杂性。

添加依赖 ​

在项目中集成 Quartz 及其扩展工具,只需添加相应的 Maven 依赖。由于 tio-boot 已经内置了 tio-utils,无需额外引入 tio-utils,只需添加 Quartz 的依赖即可。

在 pom.xml 中添加以下依赖:

xml
<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz-jobs</artifactId>
  <version>2.3.0</version>
</dependency>

注意:确保所使用的 Quartz 版本与项目其他依赖兼容,避免版本冲突。

创建任务类 ​

定时任务的核心是作业类。通过继承 AbstractJobWithLog,可以轻松创建一个带有日志记录功能的定时任务。

以下是一个示例任务类 DemoTask,每次执行时会记录任务的执行上下文信息:

java
import org.quartz.JobExecutionContext;
import nexus.io.tio.utils.quartz.AbstractJobWithLog;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DemoTask extends AbstractJobWithLog {
  @Override
  public void run(JobExecutionContext context) throws Exception {
    log.info("任务执行上下文: {}", context);
    // 在此处添加具体的业务逻辑
  }
}

说明:

  • @Slf4j 注解:来自 Lombok,用于简化日志记录,自动生成 log 对象。
  • run 方法:需要重写该方法,编写具体的任务执行逻辑。

配置 Quartz ​

Quartz 的调度规则通过配置文件进行定义。在 src/main/resources/config 目录下创建一个名为 tio-quartz.properties 的配置文件,用于定义各个任务的调度规则。

例如,配置 DemoTask 每 10 秒执行一次:

properties
# 每10秒执行一次
demo.timetask.DemoTask = 0/10 * * * * ?

配置说明:

  • demo.timetask.DemoTask:键名用于标识具体的任务,通常包括命名空间和任务类名。
  • 0/10 * * * * ?:Cron 表达式,定义任务的执行频率。

Cron 表达式详解 ​

Cron 表达式格式 ​

Cron 表达式用于定义任务的执行时间,其格式如下:

[秒] [分] [小时] [日] [月] [周] [年]
  • 秒:0-59
  • 分:0-59
  • 小时:0-23
  • 日:1-31
  • 月:1-12
  • 周:1-7(1 代表星期日)
  • 年(可选):1970-2099

特殊字符:

  • *:表示所有取值。例如,* 在分钟位置表示每一分钟。
  • /:用于指定增量。例如,0/10 在秒位置表示从第 0 秒开始,每 10 秒执行一次。
  • ,:用于指定多个取值。例如,0,30 在分钟位置表示第 0 和第 30 分钟。
  • ?:表示不指定值,常用于日和周的位置。
  • -:表示范围。例如,10-12 在小时位置表示 10 点到 12 点。
  • L:表示最后。例如,L 在日的位置表示当月最后一天。

常用 Cron 表达式示例 ​

  1. 每 1 分钟执行一次:

    0 */1 * * * ?
  2. 每 5 分钟执行一次:

    0 */5 * * * ?
  3. 每 10 分钟执行一次:

    0 */10 * * * ?
  4. 每 30 分钟执行一次:

    0 */30 * * * ?
  5. 每 1 小时执行一次:

    0 0 */1 * * ?
  6. 每 2 小时执行一次:

    0 0 */2 * * ?
  7. 每 3 小时执行一次:

    0 0 */3 * * ?
  8. 每 6 小时执行一次:

    0 0 */6 * * ?
  9. 每 12 小时执行一次:

    0 0 0,12 * * ?
  10. 每天执行一次(即每 24 小时):

    0 0 0 * * ?

注意:Cron 表达式中的字段之间使用空格分隔,确保表达式的正确性,避免语法错误。

启动与停止 Quartz ​

为了使 Quartz 与应用程序的生命周期相绑定,需要在应用的配置类中启动 Quartz,并在应用销毁时停止 Quartz。以下是配置类的示例:

java
package nexus.io.telegram.bots.config;

import nexus.io.annotation.AConfiguration;
import nexus.io.annotation.Initialization;
import nexus.io.hook.HookCan;
import nexus.io.tio.boot.server.TioBootServer;
import nexus.io.tio.utils.quartz.QuartzUtils;

@AConfiguration
public class QuartzConfig {

  @Initialization
  public void config() {
    // 启动 Quartz 定时任务
    QuartzUtils.start();

    // 在应用销毁时停止 Quartz
    HookCan.me().addDestroyMethod(() -> {
      QuartzUtils.stop();
    });
  }
}

说明:

  • @AConfiguration 注解:标识该类为配置类。
  • @Initialization 注解:标识该方法在应用初始化时执行。
  • QuartzUtils.start():启动 Quartz 调度器,开始调度任务。
  • HookCan.me().addDestroyMethod():注册一个销毁方法,在应用关闭时调用 QuartzUtils.stop() 停止 Quartz。

注意:无需将 Quartz 与 hotswap-classloader 整合,因为 Quartz 对任务的操作是静态的,不受类加载器影响。

注意事项 ​

  1. Quartz 版本兼容性:确保所使用的 Quartz 版本与项目其他依赖兼容,避免引入冲突。
  2. Cron 表达式正确性:编写 Cron 表达式时,确保格式和字段值的正确性,可以使用在线工具验证表达式。
  3. 任务执行的幂等性:定时任务的执行逻辑应具备幂等性,避免因重复执行导致数据不一致或其他问题。
  4. 异常处理:在任务执行逻辑中,适当处理可能的异常,避免任务因异常而中断调度。
  5. 资源管理:确保任务执行过程中合理管理资源(如数据库连接、文件句柄等),防止资源泄漏。

总结 ​

通过本文的介绍,您已经了解了如何使用 tio-utils 对 Quartz 进行简单封装,以实现高效、易维护的定时任务调度。关键步骤包括添加必要的依赖、创建任务类、配置 Quartz 调度规则以及管理 Quartz 的生命周期。同时,深入理解 Cron 表达式有助于精确控制任务的执行频率和时间。借助这些工具和方法,您可以在项目中轻松集成 Quartz,提升开发效率,确保定时任务的稳定运行。

MIT Licensed