有没有办法在Java中使用Quartz只运行一次作业?我知道在这种情况下使用Quartz是没有意义的。但事实是,我有多个工作,他们多次运行。所以,我正在使用Quartz。
这甚至可能吗?
答案 0 :(得分:12)
您应该使用在特定时间触发而不重复的SimpleTrigger。 TriggerUtils有许多方便的方法来创建这类东西。
答案 1 :(得分:4)
是的,这是可能的!
JobKey jobKey = new JobKey("testJob");
JobDetail job = newJob(TestJob.class)
.withIdentity(jobKey)
.storeDurably()
.build();
scheduler.addJob(job, true);
scheduler.triggerJob(jobKey); //trigger a job inmediately
答案 2 :(得分:3)
石英> 2.0,你可以让调度程序在工作完成后取消安排任何工作:
@Override
protected void execute(JobExecutionContext context)
throws JobExecutionException {
...
// process execution
...
context.getScheduler().unscheduleJob(triggerKey);
...
}
其中triggerKey是仅运行一次的作业的ID。在此之后,工作将不再被调用。
答案 3 :(得分:3)
以下是如何使用 Quartz 2.x 立即运行TestJob
类的示例:
public JobKey runJob(String jobName)
{
// if you don't call startAt() then the current time (immediately) is assumed.
Trigger runOnceTrigger = TriggerBuilder.newTrigger().build();
JobKey jobKey = new JobKey(jobName);
JobDetail job = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
scheduler.scheduleJob(job, runOnceTrigger);
return jobKey;
}
另请参阅Quartz Enterprise Job Scheduler Tutorials→SimpleTriggers
答案 4 :(得分:2)
我不确定在Mono和Java中有多少相似的Quartz,但这似乎在.Net
TriggerBuilder.Create ()
.StartNow ()
.Build ();
答案 5 :(得分:1)
我不得不问自己,尝试配置作业并添加检查是否已经按照Marko Lahma的答案中的建议进行检查是否有意义(因为将作业安排为一次运行会导致每次运行一次)我们启动应用程序)。我找到了CommandLineRunner应用程序的示例,这些示例对我而言并不十分有效,这主要是因为我们已经拥有一个ApplicationRunner,该应用程序已用于使用Quartz调度/ cron的其他作业。我对让Quartz使用SimpleTrigger初始化这项工作感到不满意,所以我不得不寻找其他东西。
使用以下文章中的一些想法:
我能够拼凑出一个可行的实现,可以执行以下操作:
我想到了以下CommandLineRunner类:
public class BatchCommandLineRunner implements CommandLineRunner {
@Autowired
private Scheduler scheduler;
private static final Logger LOGGER = LoggerFactory.getLogger(BatchCommandLineRunner.class);
public void run(final String... args) throws SchedulerException {
LOGGER.info("BatchCommandLineRunner: running with args -> " + Arrays.toString(args));
for (final String jobName : args) {
final JobKey jobKey = findJobKey(jobName);
if (jobKey != null) {
LOGGER.info("Triggering job for: " + jobName);
scheduler.triggerJob(jobKey);
} else {
LOGGER.info("No job found for jobName: " + jobName);
}
}
}
private JobKey findJobKey(final String jobNameToFind) throws SchedulerException {
for (final JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals("DEFAULT"))) {
final String jobName = jobKey.getName();
if (jobName.equals(jobNameToFind)) {
return jobKey;
}
}
return null;
}
}
在我的一个配置类中,我添加了一个CommandLineRunner bean,该bean调用了我创建的自定义CommandLineRunner:
@Configuration
public class BatchConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(BatchConfiguration.class);
@Bean
public BatchCommandLineRunner batchCommandLineRunner() {
return new BatchCommandLineRunner();
}
@Bean
public CommandLineRunner runCommandLineArgs(final ApplicationArguments applicationArguments) throws Exception {
final List<String> jobNames = applicationArguments.getOptionValues("jobName");
LOGGER.info("runCommandLineArgs: running the following jobs -> " + ArrayUtils.toString(jobNames));
batchCommandLineRunner().run(jobNames.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
return null;
}
}
稍后,我可以通过CLI初始化这些作业,而不会影响我当前的Quartz计划作业,并且只要没有人多次通过CLI运行该命令,它就不会再运行。自从我接受ApplicationArguments之后,我必须对类型进行一些处理,然后将它们转换为String []。
最后,我可以这样称呼它:
java -jar <your_application>.jar --jobName=<QuartzRegisteredJobDetailFactoryBean>
结果是,仅当我调用该作业时,该作业才被初始化,并且它被我用于其他作业的CronTriggerFactoryBean触发器排除在外。
这里有几个假设,所以我尝试总结一下:
scheduler.setJobDetails(...)
)scheduler.setTriggers(...)
调用之外,所有内容基本上都与CronTriggerFactoryBean的工作相同答案 6 :(得分:0)
另一种解决方案:SimpleSchedulerBuilder中有一种方法.withRepeatCount(0)
:
public final int TEN_SECONDS = 10;
Trigger trigger = newTrigger()
.withIdentity("myJob", "myJobGroup")
.startAt(new Date(System.currentMillis()+TEN_SECONDS*1000)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withRepeatCount(0)
.withIntervalInMinutes(1))
.build();