🎓博主介绍:Java、Python、js全栈开发 “多面手”,精通多种编程语言和技术,痴迷于人工智能领域。秉持着对技术的热爱与执着,持续探索创新,愿在此分享交流和学习,与大家共进步。
📖DeepSeek-行业融合之万象视界(附实战案例详解100+)
📖全栈开发环境搭建运行攻略:多语言一站式指南(环境搭建+运行+调试+发布+保姆级详解)
👉感兴趣的可以先收藏起来,希望帮助更多的人
SpringBoot定时任务进阶:分布式调度器Quartz动态配置
一、引言
在现代的软件开发中,定时任务是非常常见的需求,比如数据的定时备份、定时生成报表等。Spring Boot 本身提供了简单的定时任务支持,通过 @Scheduled
注解可以方便地实现基本的定时任务。然而,当应用需要分布式部署,并且需要动态配置定时任务时,Spring Boot 自带的定时任务功能就显得力不从心了。这时,Quartz 作为一个强大的分布式调度器,就可以发挥其优势。本文将详细介绍如何在 Spring Boot 中使用 Quartz 实现动态配置的分布式定时任务。
二、Quartz 简介
2.1 什么是 Quartz
Quartz 是一个开源的作业调度框架,它可以与 Java 应用程序集成,用于创建简单或复杂的调度任务。Quartz 具有以下特点:
- 灵活性:支持多种调度方式,如简单调度、Cron 调度等。
- 分布式和集群能力:可以在多个节点上运行,实现分布式调度。
- 持久化:可以将任务信息持久化到数据库中,保证任务的可靠性。
2.2 Quartz 的核心概念
- Job:表示一个具体的任务,是一个实现了
org.quartz.Job
接口的类。 - Trigger:触发器,用于定义任务的执行时间和规则。常见的触发器有
SimpleTrigger
和CronTrigger
。 - Scheduler:调度器,负责管理和执行任务。它将 Job 和 Trigger 关联起来,根据 Trigger 的规则执行 Job。
三、Spring Boot 集成 Quartz
3.1 项目搭建
首先,创建一个新的 Spring Boot 项目,在 pom.xml
中添加 Quartz 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
3.2 配置 Quartz
在 application.properties
中添加 Quartz 相关配置:
# 配置 Quartz 数据源
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.datasource.url=jdbc:mysql://localhost:3306/quartz_demo
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3.3 创建 Job 类
创建一个简单的 Job 类,实现 org.quartz.Job
接口:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("MyJob is running at: " + LocalDateTime.now());
}
}
3.4 创建 Scheduler 配置类
创建一个配置类来配置 Scheduler:
import org.quartz.JobDetail;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.spi.JobFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
@Configuration
public class QuartzConfig {
@Bean
public JobDetailFactoryBean jobDetail() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(MyJob.class);
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
@Bean
public SimpleTriggerFactoryBean trigger(JobDetail jobDetail) {
SimpleTriggerFactoryBean triggerFactory = new SimpleTriggerFactoryBean();
triggerFactory.setJobDetail(jobDetail);
triggerFactory.setStartDelay(0L);
triggerFactory.setRepeatInterval(5000L);
triggerFactory.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
return triggerFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactory(JobFactory jobFactory, Trigger trigger, JobDetail jobDetail) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setJobFactory(jobFactory);
schedulerFactory.setJobDetails(jobDetail);
schedulerFactory.setTriggers(trigger);
return schedulerFactory;
}
}
四、Quartz 动态配置
4.1 动态添加任务
可以通过编写一个服务类来动态添加任务:
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class QuartzService {
@Autowired
private Scheduler scheduler;
public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroup, String cronExpression) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(jobName, jobGroup)
.build();
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName, jobGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.startNow()
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
}
4.2 动态修改任务
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class QuartzService {
@Autowired
private Scheduler scheduler;
public void updateJob(String jobName, String jobGroup, String cronExpression) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger != null) {
CronTrigger newTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
scheduler.rescheduleJob(triggerKey, newTrigger);
}
}
}
4.3 动态删除任务
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class QuartzService {
@Autowired
private Scheduler scheduler;
public void deleteJob(String jobName, String jobGroup) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
scheduler.deleteJob(jobKey);
}
}
五、分布式调度
5.1 配置集群
为了实现分布式调度,需要在 application.properties
中添加集群配置:
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
5.2 原理
Quartz 的集群是通过数据库来实现的。多个节点共享同一个数据库,每个节点会定期检查数据库中的任务信息,并根据任务的状态和调度规则来执行任务。当一个节点执行任务时,会将任务的状态标记为已执行,其他节点就不会再执行该任务。
六、总结
本文详细介绍了如何在 Spring Boot 中使用 Quartz 实现动态配置的分布式定时任务。通过集成 Quartz,我们可以灵活地管理定时任务,实现任务的动态添加、修改和删除。同时,利用 Quartz 的集群功能,可以实现分布式调度,提高系统的可靠性和性能。