1、Cron4jPlugin

Cron4jPlugin是作为JFinal的Plugin而存在的,所以使用时需要在JFinalConfig中配置,如下是代码示例:

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

如上所示创建插件、addTask 传入参数,并添加到 JFinal 即完成了基本配置,上述代码中 cp.addTask 的第一个参数用于任务调度的cron表达式,第二个参数是 Runnable 接口的一个实现类,Cron4jPlugin会根据cron表达式调用 MyTask 中的run方法。

上例中的 MyTask 除了可以使用 Runnable 实现类以外,还可以使用 ITask 接口的实现类,该接中拥有一个 stop() 方法,会在调度停止时回调它。

2、cron 表达式

cron 表达式用于定制调度规则。与 quartz 的 cron 表达式不同,Cron4jPlugin 的 cron 表达式最多只允许五部分,每部分用空格分隔开来,这五部分从左到右依次表示分、时、天、月、周,其具体规则如下:

  • 分 :从 0 到 59

  • 时 :从 0 到 23

  • 天 :从 1 到 31,字母 L 可以表示月的最后一天

  • 月 :从 1 到 12,可以别名:jan”, “feb”, “mar”, “apr”, “may”, “jun”, “jul”, “aug”, “sep”, “oct”, “nov” and “dec”

  • 周 :从 0 到 6,0 表示周日,6 表示周六,可以使用别名: “sun”, “mon”, “tue”, “wed”, “thu”, “fri” and “sat”

如上五部分的分、时、天、月、周又分别支持如下字符,其用法如下:

  • 数字 n:表示一个具体的时间点,例如 5 * * * * 表示 5 分这个时间点时执行

  • 逗号 , :表示指定多个数值,例如 3,5 * * * * 表示 3 和 5 分这两个时间点执行

  • 减号 -:表示范围,例如 1-3 * * * * 表示 1 分、2 分再到 3 分这三个时间点执行

  • 星号 *:表示每一个时间点,例如 * * * * * 表示每分钟执行

  • 除号 /:表示指定一个值的增加幅度。例如 */5表示每隔5分钟执行一次(序列:0:00, 0:05, 0:10, 0:15 等等)。再例如3-18/5 * * * * 是指在从3到18分钟值这个范围之中每隔5分钟执行一次(序列:0:03, 0:08, 0:13, 0:18, 1:03, 1:08 等等)。

在制定 cron 规则时,建议边对照上面的规则边制定表达式。

常见错误:cron4j在表达式中使用除号指定增加幅度时与linux稍有不同。例如在linux中表达式 10/3 * * * * 的含义是从第10分钟开始,每隔三分钟调度一次,而在cron4j中需要使用 10-59/3 * * * * 来表达。避免这个常见错误的技巧是:当需要使用除号指定增加幅度时,始终指定其范围。

基于上面的技巧,每隔2分钟调度一次的表达式为:0-59/2 * * * * 或者 */2 * * * * , 而不能是0/2 * * * *

以上规则不是JFinal创造,是linux通用的cron表达式规则(注意不是quartz规则),如果开发者本身具有这方面的知识,用起来会得心应手。原始文档链接:http://www.sauronsoftware.it/projects/cron4j/manual.php

两大疑问:第一个疑问是当某个任务调度抛出了异常,那么这个任务在下次被调度的时间点上还会不会被调度,答案是肯定的,不管什么时候出现异常,时间一到调度仍然会被执行。

第二个疑问是假如某个任务执行时间很长,如果这个任务上次调度后直到本次调度到来的时候还没执行完,那么本次调度是否还会进行,答案也是肯定的。

总结一句话就是:每次调度都是独立的,上次调度是否抛出异常、是否执行完,都与本次调度无关。

特别提醒:Cron4jPlugin的cron表达式与linux一样只有5个部分,与quartz这个项目的7个部分不一样,但凡在网上搜索到的7部分cron表达式都不要试图应用在Cron4jPlugin之中。