如何在 Spring 引导应用程序中测试 Quartz 作业的正常工作
How to test proper working of Quartz job in Spring Boot application
我想测试一下我的 Quartz 触发器是否像它在实践中设想的那样工作。
我的 Quartz 配置如下:
@Configuration
public class QuartzConfiguration {
@Bean
public JobDetail verificationTokenRemoverJobDetails() {
return
JobBuilder
.newJob(VerificationTokenQuartzRemoverJob.class)
.withIdentity("Job for verification token remover")
.storeDurably()
.build();
}
@Bean
public Trigger verificationTokenRemoverJobTrigger(JobDetail jobADetails) {
return
TriggerBuilder
.newTrigger()
.forJob(jobADetails)
.withIdentity("Trigger for verification token remover")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 0/2 1/1 * ? *"))
.build();
}
}
我的工作 class 看起来像:
@AllArgsConstructor
public class VerificationTokenQuartzRemoverJob implements Job {
private VerificationTokenRepository verificationTokenRepository;
@Override
public void execute(JobExecutionContext context) {
verificationTokenRepository.deleteAllByCreatedLessThan(LocalDateTime.now().minusMinutes(30));
}
}
当我在日志中启动我的 Spring 引导应用程序时,我可以意识到作业正在运行并周期性触发,但这不足以确认正常运行。
这就是我决定创建 JUnit 测试的原因。我找到了一个教程:click but an owner used a clause while(true) which according to this topic: click is not a preferred option。这里出现一个问题,是否有任何其他选项来验证 Job class 名称,触发器的身份并检查是否尽可能频繁地调用 CRON 表达式和具体作业?
如果可能的话,我将不胜感激关于如何达到理想效果的建议。
使用 SpringBoot,您可以更轻松地执行以下操作
--- 选项 1 ---
@Configuration
// This is important!
@EnableScheduling
public class Configuration{
// TODO Change to 0 0 0/2 1/1 * ? *
@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"schedule tasks using cron jobs - " + now);
}
}
完整示例:
https://www.baeldung.com/spring-scheduled-tasks
--- 选项 2-> 以编程方式 ---
@Configuration
@EnableScheduling
public class Configuration implements SchedulingConfigurer {
@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
CronTrigger cronTrigger
= new CronTrigger("* * * * * *");
taskRegistrar.setScheduler(taskExecutor());
taskRegistrar.addTriggerTask(
new Runnable() {
@Override public void run() {
System.out.println("RUN!!!");
}
},
cronTrigger
);
}
}
请注意,上面关于使用 Spring 调度的答案有一个很大的缺点:如果您只是 运行 您的应用程序的单个实例,这会很好地工作,但是一旦您扩展对于多个实例,它变得更加复杂:
您可能希望 运行 作业仅在特定时间间隔执行一次,但如果两个节点同时 运行,则作业可能会在两个节点上 运行(基本上是两次)。 Quartz 可以处理这些情况,因为它可以有一个中央数据库,如果作业已经开始,它可以通过该数据库进行协调。
使用 spring 调度作业将在两个节点上 运行。
我想测试一下我的 Quartz 触发器是否像它在实践中设想的那样工作。 我的 Quartz 配置如下:
@Configuration
public class QuartzConfiguration {
@Bean
public JobDetail verificationTokenRemoverJobDetails() {
return
JobBuilder
.newJob(VerificationTokenQuartzRemoverJob.class)
.withIdentity("Job for verification token remover")
.storeDurably()
.build();
}
@Bean
public Trigger verificationTokenRemoverJobTrigger(JobDetail jobADetails) {
return
TriggerBuilder
.newTrigger()
.forJob(jobADetails)
.withIdentity("Trigger for verification token remover")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 0/2 1/1 * ? *"))
.build();
}
}
我的工作 class 看起来像:
@AllArgsConstructor
public class VerificationTokenQuartzRemoverJob implements Job {
private VerificationTokenRepository verificationTokenRepository;
@Override
public void execute(JobExecutionContext context) {
verificationTokenRepository.deleteAllByCreatedLessThan(LocalDateTime.now().minusMinutes(30));
}
}
当我在日志中启动我的 Spring 引导应用程序时,我可以意识到作业正在运行并周期性触发,但这不足以确认正常运行。
这就是我决定创建 JUnit 测试的原因。我找到了一个教程:click but an owner used a clause while(true) which according to this topic: click is not a preferred option。这里出现一个问题,是否有任何其他选项来验证 Job class 名称,触发器的身份并检查是否尽可能频繁地调用 CRON 表达式和具体作业?
如果可能的话,我将不胜感激关于如何达到理想效果的建议。
使用 SpringBoot,您可以更轻松地执行以下操作
--- 选项 1 ---
@Configuration
// This is important!
@EnableScheduling
public class Configuration{
// TODO Change to 0 0 0/2 1/1 * ? *
@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"schedule tasks using cron jobs - " + now);
}
}
完整示例: https://www.baeldung.com/spring-scheduled-tasks
--- 选项 2-> 以编程方式 ---
@Configuration
@EnableScheduling
public class Configuration implements SchedulingConfigurer {
@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
CronTrigger cronTrigger
= new CronTrigger("* * * * * *");
taskRegistrar.setScheduler(taskExecutor());
taskRegistrar.addTriggerTask(
new Runnable() {
@Override public void run() {
System.out.println("RUN!!!");
}
},
cronTrigger
);
}
}
请注意,上面关于使用 Spring 调度的答案有一个很大的缺点:如果您只是 运行 您的应用程序的单个实例,这会很好地工作,但是一旦您扩展对于多个实例,它变得更加复杂: 您可能希望 运行 作业仅在特定时间间隔执行一次,但如果两个节点同时 运行,则作业可能会在两个节点上 运行(基本上是两次)。 Quartz 可以处理这些情况,因为它可以有一个中央数据库,如果作业已经开始,它可以通过该数据库进行协调。 使用 spring 调度作业将在两个节点上 运行。