Dynamic Configuration of Quartz Scheduled Tasks in Spring Boot
This article demonstrates how to implement a dynamic, non‑blocking Quartz scheduling solution in a Spring Boot application, covering Maven dependencies, database schema, initialization steps, custom job factory, listener, and common Scheduler API operations such as pause, resume, delete, and trigger.
The article introduces a dynamic configuration approach for Quartz scheduled tasks, addressing the drawbacks of static XML‑based scheduling that requires application restarts for changes.
Maven dependencies for Quartz and Spring context support are provided:
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>A MySQL task table ( sys_task) is defined to store job metadata such as name, description, cron expression, bean class, status, group, and audit fields.
CREATE TABLE `sys_task` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_name` varchar(255) DEFAULT NULL COMMENT '任务名',
`description` varchar(255) DEFAULT NULL COMMENT '任务描述',
`cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron表达式',
`bean_class` varchar(255) DEFAULT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名',
`job_status` varchar(255) DEFAULT NULL COMMENT '任务状态',
`job_group` varchar(255) DEFAULT NULL COMMENT '任务分组',
`create_user` varchar(64) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user` varchar(64) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;Implementation steps :
Start the Spring Boot project; the ScheduleJobInitListener (a CommandLineRunner) loads tasks.
Read enabled tasks from the database and add them to the Quartz Scheduler.
The scheduler automatically triggers the jobs based on their CronTrigger.
A custom JobFactory (extending AdaptableJobFactory) injects Spring beans into job instances.
Key code snippets :
Quartz configuration bean:
@Configuration
public class QuartzConfigration {
@Autowired
JobFactory jobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setOverwriteExistingJobs(true);
bean.setQuartzProperties(quartzProperties());
bean.setJobFactory(jobFactory);
return bean;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("/config/quartz.properties"));
pf.afterPropertiesSet();
return pf.getObject();
}
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}Listener that initializes tasks:
@Component
@Order(1)
public class ScheduleJobInitListener implements CommandLineRunner {
@Autowired
TaskService scheduleJobService;
@Override
public void run(String... args) throws Exception {
try {
scheduleJobService.initSchedule();
} catch (Exception e) {
e.printStackTrace();
}
}
}Adding a job to the scheduler:
public void addJob(TaskDO task) {
try {
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(task.getBeanClass()).newInstance().getClass();
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(task.getJobName(), task.getJobGroup())
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(task.getJobName(), task.getJobGroup())
.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression()))
.startNow()
.build();
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}Common Scheduler API examples (pause, resume, delete, trigger, update cron):
public void pauseJob(TaskDO task) throws SchedulerException {
JobKey key = JobKey.jobKey(task.getJobName(), task.getJobGroup());
scheduler.pauseJob(key);
}
public void resumeJob(TaskDO task) throws SchedulerException {
JobKey key = JobKey.jobKey(task.getJobName(), task.getJobGroup());
scheduler.resumeJob(key);
}
public void deleteJob(TaskDO task) throws SchedulerException {
JobKey key = JobKey.jobKey(task.getJobName(), task.getJobGroup());
scheduler.deleteJob(key);
}
public void runJobNow(TaskDO task) throws SchedulerException {
JobKey key = JobKey.jobKey(task.getJobName(), task.getJobGroup());
scheduler.triggerJob(key);
}
public void updateJobCron(TaskDO task) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
scheduler.rescheduleJob(triggerKey, trigger);
}The article concludes with a link to a live demo, source code repository, and Quartz documentation, inviting readers to try the implementation and explore additional API features.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
