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 ?";
, isValid
testing返回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