cron4j 使用指南

Cron4jPlugin 是一个集成在 Java 中的任务调度插件,通过使用 Cron4jPlugin,可以方便地利用通用的 cron 表达式实现任务调度功能。

入门示例

添加依赖

在项目的 pom.xml 文件中添加以下依赖:

<dependency>
  <groupId>com.litongjava</groupId>
  <artifactId>java-db</artifactId>
  <version>${java-db.version}</version>
</dependency>
<dependency>
  <groupId>it.sauronsoftware.cron4j</groupId>
  <artifactId>cron4j</artifactId>
  <version>2.2.5</version>
</dependency>

依赖说明:

  • java-db:JavaDB 插件依赖。
  • cron4j:cron4j 任务调度框架。

Cron4jPluginConfig 配置类

Cron4jPluginConfig 是用于初始化和配置 Cron4j 插件的配置类。该类通过 @AConfiguration 注解标记为配置类,cron4jPlugin 方法通过 @ABean 注解标记为 Bean 方法,在框架启动时执行该方法,并将返回的 Cron4jPlugin 实例放入 Bean 容器中。destroyMethod 指定服务关闭时调用的方法,以便关闭插件。

需要注意的是,cron4j 的表达式格式与其他框架和语言有所不同,具体可以参考文档:Cron4jPlugin 文档open in new window

import com.litongjava.db.aop.annotation.Bean;
import com.litongjava.db.aop.annotation.Configuration;
import com.litongjava.db.plugin.cron4j.Cron4jPlugin;
import com.litongjava.tio.web.hello.task.MyTask;

@AConfiguration
public class Cron4jPluginConfig {

  @ABean(destroyMethod = "stop")
  public Cron4jPlugin cron4jPlugin() {
    Cron4jPlugin cp = new Cron4jPlugin();
    // 每1分钟执行一次
    cp.addTask("* * * * *", new MyTask());
    cp.start();
    return cp;
  }
}

创建任务类

package com.litongjava.tio.web.hello.task;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MyTask implements Runnable {

  @Override
  public void run() {
    log.info("执行任务");
  }
}

启动服务后,您可以测试任务是否按照预期执行。

Cron4jPlugin

1. Cron4jPlugin 简介

Cron4jPlugin 是 JavaDb 的插件之一,使用时需要在 JavaDbConfig 中进行配置。以下是基本配置示例:

Cron4jPlugin cp = new Cron4jPlugin();
cp.addTask("* * * * *", new MyTask());
me.add(cp);

如上所示,创建插件并通过 addTask 添加任务。第一个参数是 cron 表达式,第二个参数是 Runnable 接口的实现类。Cron4jPlugin 会根据 cron 表达式定时调用 MyTask 中的 run 方法。

除了使用 Runnable 实现类,您还可以使用 ITask 接口的实现类,该接口包含一个 stop() 方法,会在调度停止时调用。

2. cron 表达式详解

cron 表达式用于定义调度规则。与 Quartz 的 cron 表达式不同,Cron4jPlugin 的 cron 表达式最多包含五部分,用空格分隔,分别表示:分钟、小时、天、月、周。具体规则如下:

  • 分钟:从 0 到 59
  • 小时:从 0 到 23
  • :从 1 到 31,字母 L 可以表示月的最后一天
  • :从 1 到 12,或使用别名(如 "jan" 表示 1 月)
  • :从 0 到 6,0 表示周日,6 表示周六,也可以使用别名(如 "sun" 表示周日)

这些部分支持以下字符组合:

  • 数字 n:表示一个具体的时间点(例如 5 * * * * 表示在每小时的第 5 分钟执行任务)。
  • 逗号 ,:表示指定多个值(例如 3,5 * * * * 表示在第 3 和第 5 分钟执行任务)。
  • 减号 -:表示范围(例如 1-3 * * * * 表示从第 1 分钟到第 3 分钟执行任务)。
  • 星号 *:表示所有可能的值(例如 * * * * * 表示每分钟执行一次)。
  • 除号 /:表示指定间隔时间(例如 */5 * * * * 表示每隔 5 分钟执行一次)。

常见错误:

cron4j 的表达式与 Linux 的表达式稍有不同。例如,Linux 中的 10/3 * * * * 表示从第 10 分钟开始每隔 3 分钟执行一次,而在 cron4j 中需要使用 10-59/3 * * * * 来表达相同的意思。建议在使用除号指定间隔时始终指定范围,以避免错误。

两个常见问题:

  1. 任务调度抛出异常时,是否还会继续调度?
    答案是肯定的。不管任务何时抛出异常,一旦达到下一个调度时间点,任务仍会执行。

  2. 任务执行时间较长时,是否会影响下一次调度?
    答案是不会。每次调度都是独立的,上次调度的执行情况不会影响下一次调度。

特别提醒:

Cron4jPlugin 的 cron 表达式只有 5 个部分,与 Quartz 的 7 个部分不同。在使用 cron 表达式时,请确保遵循 cron4j 的规则。

使用外部配置文件

除了硬编码的方式,还可以通过外部配置文件灵活配置调度策略。以下是外部配置文件的示例:

cron4j=task1, task2
task1.cron=* * * * *
task1.class=com.xxx.TaskAaa
task1.daemon=true
task1.enable=true

task2.cron=* * * * *
task2.class=com.xxx.TaskBbb
task2.daemon=true
task2.enable=false

配置文件中,cron4j 是配置名称,可以自定义。task1task2 是任务名称,后续配置以这些任务名称为前缀。

创建 Cron4jPlugin 对象时,可以使用以下方式加载配置文件:

Cron4jPlugin cp = new Cron4jPlugin("config.txt");
Cron4jPlugin cpWithName = new Cron4jPlugin("config.txt", "cron4j");

Cron4jPlugin cpWithPropKit = new Cron4jPlugin(PropKit.use("config.txt"));
Cron4jPlugin cpWithPropKitAndName = new Cron4jPlugin(PropKit.use("config.txt"), "cron4j");

me.add(cp);

高级用法

除了调度 Java 类,还可以直接调度外部应用程序,例如启动 Windows 或 Linux 下的某个可执行程序。以下是代码示例:

String[] command = { "C:\\tomcat\\bin\\catalina.bat", "start" };
String[] envs = { "CATALINA_HOME=C:\\tomcat", "JAVA_HOME=C:\\jdks\\jdk5" };
File directory = new File("C:\\MyDirectory");
ProcessTask task = new ProcessTask(command, envs, directory);

cron4jPlugin.addTask(task);
me.add(cron4jPlugin);

如上所示,通过创建 ProcessTask 对象并添加到插件中,可以实现对外部程序的调度。更详细的用法可以参考 Cron4jPlugin.java 源代码中的注释。

通过以上内容,您可以快速上手使用 Cron4jPlugin 实现各种任务调度。