假设我的Cron表达式如0 0 12 1/1 *? *由于某些原因服务器在11:50到12:05之间停止,并且在这种情况下12:05之后再次开始服务器如何在服务器启动后触发错过的预定Cron表达式?石英是否有解决上述问题的任何解决方案。
答案 0 :(得分:0)
请参阅Quartz文档tutorials或this关于“失火指令”的精彩文章,这些指令是Quartz触发器用于恢复错过的作业执行的策略。
如果您想要容忍服务器关闭/崩溃,您需要将Qaurtz配置为使用持久性Job Store来使JDBCJobStore更好地“记住”崩溃前的最后一次作业。
更新:请参阅解释如何创建可恢复作业 的this answer。
答案 1 :(得分:0)
我也遇到过想要在服务器重启时运行最后一个计划作业的问题。
我找到的解决方案是返回触发器的一个时间间隔并计算下一个触发时间。通过迭代所有触发器,可以确定触发器过去应该触发的最近时间。
计算每次射击之间的间隔:
Date nextFireTime = trigger.getNextFireTime();
Date subsequentFireTime = trigger.getFireTimeAfter(nextFireTime);
long interval = subsequentFireTime.getTime() - nextFireTime.getTime();
找到下一次的射击时间,直到过去的时间间隔:
Date previousPeriodTime = new Date(System.currentTimeMillis() - interval);
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime);
我发现如果您使用的是CronTrigger
,这可以防止您过去要求过火时间。要解决此问题,我修改了开始时间,因此上面的代码段变为:
Date originalStartTime = trigger.getStartTime(); // save the start time
Date previousPeriodTime = new Date(originalStartTime.getTime() - interval);
trigger.setStartTime(previousPeriodTime);
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime);
trigger.setStartTime(originalStartTime); // reset the start time to be nice
遍历所有触发器,找到过去最近的触发器:
for (String groupName : scheduler.getTriggerGroupNames()) {
for (String triggerName : scheduler.getTriggerNames(groupName)) {
Trigger trigger = scheduler.getTrigger(triggerName, groupName);
// code as detailed above...
interval = ...
previousFireTime = ...
}
}
此代码可以重构为辅助方法或类。实际上,我在子类委托触发器中使用上述算法,然后将其置于按先前触发时间排序的集合中。