我有一个使用Sprint Boot - Java 8的应用程序,其中包含一个quartz任务,我在启动时进行配置并设置了一个计划。该任务会按照计划自动运行,就像quartz任务一样。然而,现在我希望用户能够通过前端页面上的按钮手动触发这些任务,而不会影响该任务的正常调度。以下是所有相关文件。
现在这个程序按照预定时间表运行。根据yml文件中的cron配置,
我到底做错了什么?如何使这个工作按计划自动运行,同时也能在手动请求时执行?
我正在使用 Spring Boot
application.yml
quartz:
fooCron: 0 0 1 * * ?
fooGroup: foo-quartz-group
QuartzConfig.java
@Configuration
@ConfigurationProperties(prefix = "quartz")
public class QuartzConfig {
private String fooCron;
private String fooGroup;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private DataSource dataSource;
@Bean
public SchedulerFactoryBean quartzScheduler() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
Trigger[] triggers = {fooTrigger().getObject()};
SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();
quartzScheduler.setJobFactory(jobFactory);
quartzScheduler.setTransactionManager(transactionManager);
quartzScheduler.setDataSource(dataSource);
quartzScheduler.setOverwriteExistingJobs(true);
quartzScheduler.setSchedulerName("foo-scheduler");
quartzScheduler.setQuartzProperties(quartzProperties());
quartzScheduler.setTriggers(triggers);
return quartzScheduler;
}
@Bean
public CronTriggerFactoryBean fooTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(fooJob().getObject());
cronTriggerFactoryBean.setCronExpression(fooCron);
cronTriggerFactoryBean.setGroup(fooGroup);
return cronTriggerFactoryBean;
}
@Bean
public JobDetailFactoryBean fooJob() {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(FooJob.class);
jobDetailFactoryBean.setGroup(fooGroup);
jobDetailFactoryBean.setDurability(true);
return jobDetailFactoryBean;
}
@Bean
public Properties quartzProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz/quartz.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
}
return properties;
}
//setters
}
FooJob.java
@Service
public class FooJob implements Job {
private final FooRepository fooRepo; //This is a repository class annotated with @Repository.
public FooJob(FooRepository fooRepo) {
this.fooRepo = fooRepo;
}
@Override
public void execute(final JobExecutionContext context) throws JobExecutionException {
//do stuff
}
}
现在这个程序按照预定时间表运行。根据yml文件中的cron配置,
0 0 1 * * ?
,该作业每天凌晨1点执行。很棒!但是现在我想手动执行它。因此,我构建了一个控制器来接收来自UI的手动触发请求。
QuartzController.java
@RestController
@RequestMapping("/quartz")
public class QuartzController {
private SchedulerFactoryBean schedulerFactoryBean;
private Scheduler scheduler;
public DevopsController(final SchedulerFactoryBean quartzScheduler) {
this.schedulerFactoryBean = quartzScheduler;
scheduler = schedulerFactoryBean.getScheduler();
}
@PostMapping("/execute")
public ResponseEntity executeJob() {
HttpStatus status = OK;
try {
TriggerKey triggerKey = new TriggerKey("fooTrigger", "foo-quartz-group");
Trigger trigger = scheduler.getTrigger(triggerKey);
ScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).withRepeatCount(0);
JobDetail jobDetail = scheduler.getJobDetail(trigger.getJobKey());
Trigger newTrigger = TriggerBuilder.newTrigger()
.forJob(jobDetail)
.startNow()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder)
.startAt(Date.from(LocalDate.now().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
.build();
//I have tried all 3 of the following lines
scheduler.scheduleJob(jobDetail, new HashSet<>(Arrays.asList(trigger)), true);
//scheduler.addJob(jobDetail, true);
//scheduler.rescheduleJob(triggerKey, newTrigger);
} catch (SchedulerException e) {
status = BAD_REQUEST;
}
return new ResponseEntity<>(status);
}
}
但是每次运行应用程序并调用控制器的 scheduleJob
方法时,我会在控制台中收到以下错误:
org.quartz.SchedulerException: Job instantiation failed
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:45)
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
Caused by: java.lang.InstantiationException: com.test.jobs.FooJob
at java.lang.Class.newInstance(Class.java:427)
at org.springframework.scheduling.quartz.AdaptableJobFactory.createJobInstance(AdaptableJobFactory.java:58)
at org.springframework.scheduling.quartz.SpringBeanJobFactory.createJobInstance(SpringBeanJobFactory.java:74)
at com.test.config.AutowiringSpringBeanJobFactory.createJobInstance(AutowiringSpringBeanJobFactory.java:27)
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:41)
... 2 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.test.jobs.FooJob.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 6 common frames omitted
我到底做错了什么?如何使这个工作按计划自动运行,同时也能在手动请求时执行?
我正在使用 Spring Boot
1.5.9.RELEASE
和 Quartz 2.2.1
。
scheduler.triggerJob(JobKey.jobKey("Your Job Key"));
Ķ┐Öµ«Ąõ╗ŻńĀüõĖŹÕż¤ÕÉŚ’╝¤ - undefined