简体   繁体   English

使用石英调度程序在弹簧启动中进行动态作业调度

[英]Dynamic job scheduling in spring boot with quartz scheduler

I want to schedule jobs dynamically based on the schedule configuration provided by the user from the UI. 我想根据用户从UI提供的计划配置动态地计划作业。 When ever user save the new schedule configuration from the UI then the process has to invoke new job with the new scheduled parameters. 每当用户从UI保存新的计划配置时,该过程就必须使用新的计划参数来调用新作业。 There can be n number of configurations as such to execute the same job. 可以有n种配置来执行同一作业。 Spring supports the implementation of job detail and trigger as following. Spring支持作业细节和触发器的实现,如下所示。

Defining jobdetail: 定义工作细节:

@Bean
public JobDetail jobDetail() {
    return JobBuilder.newJob().ofType(SampleJob.class)
      .storeDurably()
      .withIdentity("Qrtz_Job_Detail")  
      .withDescription("Invoke Sample Job service...")
      .build();
}

Defining trigger: 定义触发器:

@Bean
public Trigger trigger(JobDetail job) {
    return TriggerBuilder.newTrigger().forJob(job)
      .withIdentity("Qrtz_Trigger")
      .withDescription("Sample trigger")
      .withSchedule(simpleSchedule().repeatForever().withIntervalInHours(1))
      .build();
}

How can I pass the parameters for job detail and trigger dynamically based on the parameters provided by the user? 如何传递作业详细信息的参数,并根据用户提供的参数动态触发?

The easiest way is to make some configuration by extending SpringBeanJobFactory and @Override createJobInstance method. 最简单的方法是通过扩展进行一些配置SpringBeanJobFactory@Override createJobInstance方法。 Then you need to define SchedulerFactoryBean and finally your Scheduler : 然后,您需要定义SchedulerFactoryBean ,最后定义您的Scheduler

@Configuration
public class SchedulerConfiguration {

    public class AutowireCapableBeanJobFactory extends SpringBeanJobFactory {

        private final AutowireCapableBeanFactory beanFactory;

        @Autowired
        public AutowireCapableBeanJobFactory(AutowireCapableBeanFactory beanFactory) {
            Assert.notNull(beanFactory, "Bean factory must not be null");
            this.beanFactory = beanFactory;
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object jobInstance = super.createJobInstance(bundle);
            this.beanFactory.autowireBean(jobInstance);
            this.beanFactory.initializeBean(jobInstance, null);
            return jobInstance;
        }
    }

    @Bean
    public SchedulerFactoryBean schedulerFactory(ApplicationContext applicationContext) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(new AutowireCapableBeanJobFactory(applicationContext.getAutowireCapableBeanFactory()));
        return schedulerFactoryBean;
    }

    @Bean
    public Scheduler scheduler(ApplicationContext applicationContext) throws SchedulerException {
        Scheduler scheduler = schedulerFactory(applicationContext).getScheduler();
        scheduler.start();
        return scheduler;
    }
}

Then anywhere in your application, for example in a RestController you can access the scheduler and schedule a new job: 然后,您可以在应用程序中的任何位置(例如在RestController中)访问调度程序并调度新作业:

@RestController
public class ScheduleController {

    @Autowired
    private Scheduler scheduler;

    @GetMapping(value = "/schedule/{detail}/{desc}")
    public String scheduleJob(@PathVariable(value = "detail") String detail, @PathVariable(value = "desc") String desc) throws SchedulerException {
        JobDetail job = newJob(detail, desc);
        return scheduler.scheduleJob(job, trigger(job)).toString();
    }

    private JobDetail newJob(String identity, String description) {
        return JobBuilder.newJob().ofType(SimpleJob.class).storeDurably()
                .withIdentity(JobKey.jobKey(identity))
                .withDescription(description)
                .build();
    }

    private SimpleTrigger trigger(JobDetail jobDetail) {
        return TriggerBuilder.newTrigger().forJob(jobDetail)
                .withIdentity(jobDetail.getKey().getName(), jobDetail.getKey().getGroup())
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1))
                .build();
    }
}

You can control all schedules (pause, stop, restart, delete, etc...) from your Scheduler - look at the documentation 您可以从Scheduler控制所有时间表(暂停,停止,重新启动,删除等)- 查看文档

This is what JobDataMap parameters are for. 这就是JobDataMap参数的用途。 You can use these parameters to pass arbitrary parameters to your jobs and triggers. 您可以使用这些参数将任意参数传递给作业和触发器。 It is generally recommended to use String parameter values to avoid various serialization issues. 通常建议使用String参数值以避免各种序列化问题。 The JobDataMap API provides auxiliary methods that you can use to convert Strings-valued JobDataMap parameter values to various basic Java objects (Integer, Long, Double, Boolean, etc.). JobDataMap API提供了一些辅助方法,可用于将字符串值的JobDataMap参数值转换为各种基本Java对象(整数,长整数,双精度,布尔型等)。

Please note that JobDataMap parameters specified on the JobDetail level can be overridden on the Trigger level. 请注意,在JobDetail级别上指定的JobDataMap参数可以在Trigger级别上被覆盖。 On the JobDetail level, you typically specify common parameters and/or defaults that should be used for all job executions and you override these defaults and/or add new parameters on the Trigger level. 在JobDetail级别上,通常可以指定用于所有作业执行的通用参数和/或默认值,并覆盖这些默认值和/或在Trigger级别上添加新参数。

For details, please refer to Quartz Javadoc: 有关详细信息,请参考Quartz Javadoc:

JobBuilder.html#usingJobData JobBuilder.html#usingJobData

TriggerBuilder.html#usingJobData TriggerBuilder.html#usingJobData

JobDataMap.html JobDataMap.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM