Quartz:永远不会执行的Cronexpression式

我知道这里有一个重复,这可能是我的情况,尽pipe它应该得到一些更好的解释,我将尝试在这里提供。

我使用Spring应用程序上下文来处理Java Web应用程序。 在这种情况下,我使用Quartz来定义计划任务。 这些作业是由.properties文件中定义的cron触发的。

Spring上下文embedded在war中,而.properties文件位于应用程序服务器上(在这种情况下,Tomcat)。

这样做很好,可以根据环境(开发,集成,生产等)定义不同的cron。

现在,当我在自己的计算机上本地运行这个应用程序时,我不希望这些作业被执行。 有没有办法写一个永远不会触发的cronexpression式?

使用远在未来的expression

使用org.quartz.CronExpression一些快速testing。

 String exp = "0 0 0 1 1 ? 3000"; boolean valid = CronExpression.isValidExpression(exp); System.out.println(valid); if (valid) { CronExpression cronExpression = new CronExpression(exp); System.out.println(cronExpression.getNextValidTimeAfter(new Date())); } 

当我做String exp = "# 0 0 0 1 1 ?";isValidtesting返回false

有了上面的例子,输出结果如下:

 true null 

含义:

  • 该expression式是有效的;
  • 没有即将到来的date与此expression式匹配。

对于调度程序接受cron触发器,后者必须匹配未来的date。

我试了好几年,发现一旦年份高于2300,Quartz似乎不再打扰了(尽pipe我没有在Quartz 2的文档中发现一个最大的值)。 可能有一个更干净的方法来做到这一点,但这将满足我现在的需要。

所以最后我提出的cron是0 0 0 1 1 ? 2200 0 0 0 1 1 ? 2200

石英1变种

请注意,在Quartz 1中, 2099是最后一个有效年份 。 因此,您可以使用Maciej Matys的build议调整您的cronexpression式: 59 59 23 31 12 ? 2099 59 59 23 31 12 ? 2099

替代方法:使用过去的date

Arnaud Denoyelle提出了一些更优雅的东西,我上面的testingcertificate这是一个正确的expression方式:与其select遥远的未来date,不如select远古的date:

0 0 0 1 1 ? 1970 0 0 0 1 1 ? 1970 (根据Quartz文档的第一个有效expression式)。

这个解决scheme虽然不起作用。

hippofluff强调说,Quartz将会检测到过去的一个expression式永远不会再被执行,因此抛出一个exception。

 org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire. 

这似乎已经在石英很长一段时间了 。

经验教训:testing并非万无一失

这突出了我的testing的一个弱点:如果你想testing一个CronExpression ,记住它必须有一个nextValidTime 1 。 否则,您将传递给它的调度程序将仅以上述exception拒绝它。

我会build议适应testing代码如下:

 String exp = "0 0 0 1 1 ? 3000"; boolean valid = CronExpression.isValidExpression(exp); if (valid) { CronExpression cronExpression = new CronExpression(exp); valid = cronExpression.getNextValidTimeAfter(new Date()) != null; } System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail.")); 

你去了:不需要思考,只需要阅读输出。


1这是我testingArnaud的解决scheme让我变傻,并certificate我的testing不能certificate我忘记的部分。

从技术上讲,可选Quartz年份字段的有效值是1970-2099,所以2300不是预期值。 我假设你真的需要这样做,你的Quartz版本试图强制执行有效的cron语法(第1-31天,第1-12天,等等)。

我目前在Rails的Resque-scheduler中使用下面的代码,它接受validation的crontab格式的日程安排信息来创build一个手动运行的testing作业:

 cron: "0 5 31 2 *" 

跑步之前耐心等待2月31日凌晨。 对于Quartz crontrigger中的等价物,请尝试下面这一行或其一些变体:

 0 0 5 31 2 ? 

试试这个: 59 59 23 31 12 ? 2099 59 59 23 31 12 ? 2099