java - Quartz CronTrigger 未在指定的 startAt() 时间触发

标签 java spring quartz-scheduler job-scheduling crontrigger

我有一个场景,我需要安排一项必须每天在特定时间执行的作业。当我将特定时间安排为调度程序的开始时间时, quartz 不会在设置的开始时间触发作业,而是会在下一个周期(即 24 小时延迟后)触发。即使检查 nextFireTime,我们也会得到一个延迟一天。

例如: 我需要每天安排一项工作在晚上 6 点运行。并于今天下午 5 点(2018 年 3 月 27 日)开始。作业未开始,nextFireTime 为 2018 年 3 月 28 日下午 6 点。

<小时/>

代码片段:

<小时/>
Date startDateTime = new Date(scheduler.getStartDateTime());
Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime(startDateTime);
int hours = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleTriggerName, schdeuleGroupName).startAt(startDateTime).withSchedule(dailyAtHourAndMinute(hours, minutes)).build();
JobDetail jobDetail = this.getJobDetail(schdeuleJobName, schdeuleGroupName);
<小时/>

Spring 的调度程序配置

<小时/>
SchedulerFactoryBean schedulerFactoryBean= new SchedulerFactoryBean();

QuartzAutowireBeanFactory jobFactory = new QuartzAutowireBeanFactory();
jobFactory.setApplicationContext(applicationContext);
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.scheduleJob(jobDetail, trigger)// scheduling the job
<小时/>

最佳答案

解决方案

一个类轮:

Cron only handles 1-minute resolutions

传递给 startAt() 函数的开始时间是毫秒级的时间戳,而 cron 确实支持分钟级。

所以简单的解决方案是使用日历将分钟和秒设置为零。

calendar.setTime(startDateTime);
            calendar.set(Calendar.SECOND, 0); // this was the solution
            calendar.set(Calendar.MILLISECOND, 0); // this was the solution
            int hours = calendar.get(Calendar.HOUR_OF_DAY);
            int minutes = calendar.get(Calendar.MINUTE);
            trigger = TriggerBuilder.newTrigger();
            trigger.startAt(calendar.getTime()).withSchedule(dailyAtHourAndMinute(hours, minutes));

详细一: 最后我得到了这种行为的原因,在调试时我看到它设置了 24 小时的延迟,但是当打印时间时,它将采用 hh:mm:00 格式,我的意思是输出会将秒部分设置为默认 00 ,所以问题是作为参数传递的开始时间是通过 UI 组成的时间戳,由秒和毫秒组成,所以在阅读 Cron 格式后,我开始知道它支持直到分钟分辨率,所以无论它使用什么地方来获取时间戳 startAt(startDateTime) 中的

CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleTriggerName, schdeuleGroupName).startAt(startDateTime).withSchedule(dailyAtHourAndMinute(hours, minutes)).build();

它将通过跳过秒和毫秒部分来计算下一次运行。

关于java - Quartz CronTrigger 未在指定的 startAt() 时间触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49512966/

相关文章:

java - 批处理 Java 帮助

java - 我可以知道 ScheduledThreadPoolExecutor 中等待执行的任务数量吗?

java - 我应该关闭使用 java.nio.file.Files.newInputStream 创建的 Streams 吗?

java - 将 Spring Boot 应用程序部署到 Elastic Beanstalk 时出现 502 Bad Gateway

java - Spring AOP,切入点表达式 : annotation with specific param

Java Quartz 作业持久化

java - Firefox Webdriver Selenium "No protocol specified"、Debian(Wheezy)、服务、脚本

java - 开始使用 Oracle 数据库

java - Spring 启动: What is causing this TransientDataAccessResourceException?

java - 获取非 servlet 类中的上下文路径