希望成为一个面对任何事情都能从容面对的人
Quartz是什么
- 开源的企业级任务调度框架
- 在某个时间点做某件事情,核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作
Quartz能干什么
- 场景1
每天晚上12点定时备份数据库里重要的数据
- 场景2
会员到期提醒,在你会员快要到期的时候,给你发邮件提醒你会员到期进行续费
Quartz核心概念
- 任务(job):就是执行的工作内容(业务逻辑)。Quartz提供Job接口来支持任务定义。
- 触发器(Trigger):定义触发Job执行的时间触发规则(执行时间点)。Quartz提供Trigger类及其子类来支持触发器功能。
- 调度器(Scheduler):Quartz提供Scheduler接口(start),将工作任务和触发器进行绑定,保证任务可以在正确的时间执行。
Quartz官网
Quartz的HelloWorld程序
1.引入pom坐标
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
2. 定义要执行的任务
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class MyJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("HelloWorld:" + new Date());
}
}
3. 创建触发任务相关的schedule
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class TestMyJob {
public static void main(String[] args) {
// 创建jobDetail,并把要执行的任务放进去
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1")
.build();
// 创建trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1).repeatForever())
.build();
// 创建scheduler
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 运行结果
HelloWorld:Tue Aug 29 21:43:42 CST 2023
HelloWorld:Tue Aug 29 21:43:43 CST 2023
HelloWorld:Tue Aug 29 21:43:44 CST 2023
HelloWorld:Tue Aug 29 21:43:45 CST 2023
HelloWorld:Tue Aug 29 21:43:46 CST 2023
HelloWorld:Tue Aug 29 21:43:47 CST 2023
HelloWorld:Tue Aug 29 21:43:48 CST 2023
HelloWorld:Tue Aug 29 21:43:49 CST 2023
HelloWorld:Tue Aug 29 21:43:50 CST 2023
HelloWorld:Tue Aug 29 21:43:51 CST 2023
Quartz架构图
Quartz的上下文对象
使用usingJobData携带需要传输的数据
public class TestMyJob {
public static void main(String[] args) {
// 创建jobDetail,并把要执行的任务放进去
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1")
.usingJobData("id", "1234567")
.usingJobData("name", "张三")
.build();
// 创建trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1).repeatForever())
.build();
// 创建scheduler
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在执行任务的时候获取
public class MyJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
Object id = jobDataMap.get("id");
Object name = jobDataMap.get("name");
System.out.println("上面传过来的id: " + id);
System.out.println("上面传过来的name: " + name);
}
}
运行结果
上面传过来的id: 1234567
上面传过来的name: 张三
控制开始时间和结束时间
startAt():任务延迟多久开始执行
endAt():任务执行多久
public class TestMyJob {
public static void main(String[] args) {
// 创建jobDetail,并把要执行的任务放进去
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1")
.usingJobData("id", "1234567")
.usingJobData("name", "张三")
.build();
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 5000);
Date endDate = new Date();
endDate.setTime(startDate.getTime() + 5000);
// 创建trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.startAt(startDate)
.endAt(endDate)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1).repeatForever())
.build();
// 创建scheduler
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
延迟五秒开始,任务只执行五秒
CronTrigger触发器
- SimpleTrigger:应用场景(固定时间间隔的调度任务),使用方式(通过设置触发器的属性:开始时间、结束时间、重复次数、重复间隔等)
- CronTrigger:应用场景(指定时间点的调度任务,例如每天凌晨两点执行一次),使用方式(通过Cron定义表达式)
CronTrigger允许用户更准确地控制任务的运行日期和时间,而不仅仅是定义工作的频度。
使用示例
public class TestMyJob {
public static void main(String[] args) {
// 创建jobDetail,并把要执行的任务放进去
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1")
.build();
// 创建trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 39 22 * * ?"))
.build();
// 创建scheduler
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
SpringBoot整合Quartz完整使用流程
1. 引用依赖,2.3.2稳定
<dependencies>
...
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
...
</dependencies>
2.Quartz配置类
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
@Bean
public Scheduler scheduler() throws SchedulerException {
return StdSchedulerFactory.getDefaultScheduler();
}
}
3.创建Quartz任务类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
@Component
public class MyQuartzJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("Quartz任务执行!");
}
}
4.创建一个Quartz工具类,用于添加、暂停、删除、修改任务等操作。
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class QuartzUtils {
@Autowired
private Scheduler scheduler;
public void addJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException {
scheduler.scheduleJob(jobDetail, trigger);
}
public void pauseJob(JobKey jobKey) throws SchedulerException {
scheduler.pauseJob(jobKey);
}
public void resumeJob(JobKey jobKey) throws SchedulerException {
scheduler.resumeJob(jobKey);
}
public void deleteJob(JobKey jobKey) throws SchedulerException {
scheduler.deleteJob(jobKey);
}
public void updateJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException {
scheduler.rescheduleJob(trigger.getKey(), trigger);
}
}
5. 创建Jobdetails
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.util.QuartzUtils;
@Component
public class MyQuartzJobDetail {
@Autowired
private QuartzUtils quartzUtils;
public void addJob() throws SchedulerException {
// 创建JobDetail实例,保存关于要执行的job的信息。这里使用了刚刚创建的MyQuartzJob。
JobDetail jobDetail = JobBuilder.newJob(MyQuartzJob.class)
.withIdentity("myQuartzJob", "group1") // 第一个参数是名称,第二个参数是组名,方便进行管理。
.build();
// 创建Trigger实例,告诉scheduler何时开始执行job。这里指定了立即执行。
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myQuartzTrigger", "group1") // 名称和组名 .startNow() // 立即开始执行任务。
.build();
// 将job与trigger关联起来。
quartzUtils.addJob(jobDetail, trigger); // 使用前面创建的工具类方法。
}
工具类使用示例
1.addJob方法:
QuartzUtils quartzUtils = new QuartzUtils();
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("myQuartzJob", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myQuartzTrigger", "group1")
.startNow()
.build();
quartzUtils.addJob(jobDetail, trigger);
2.pauseJob方法:
QuartzUtils quartzUtils = new QuartzUtils();
JobKey jobKey = JobKey.jobKey("myQuartzJob", "group1");
quartzUtils.pauseJob(jobKey);
3.resumeJob方法:
QuartzUtils quartzUtils = new QuartzUtils();
JobKey jobKey = JobKey.jobKey("myQuartzJob", "group1");
quartzUtils.resumeJob(jobKey);
4.deleteJob方法:
QuartzUtils quartzUtils = new QuartzUtils();
JobKey jobKey = JobKey.jobKey("myQuartzJob", "group1");
quartzUtils.deleteJob(jobKey);
5.updateJob方法:
QuartzUtils quartzUtils = new QuartzUtils();
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("myQuartzJob", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myQuartzTrigger", "group1")
.startNow()
.build();
quartzUtils.updateJob(jobDetail, trigger);
修改一个组下的所有定时任务的执行时间
- 获取该组下的所有定时任务。
- 遍历每个定时任务,并修改它们的执行时间。
- 使用QuartzUtils工具类的updateJob方法更新每个任务的执行时间。
import org.quartz.JobKey;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
// 获取所有组名为"group1"的定时任务
GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals("group1");
List<TriggerKey> triggerKeys = scheduler.getTriggerKeys(groupMatcher);
for (TriggerKey triggerKey : triggerKeys) {
try {
// 获取定时任务对应的触发器
Trigger trigger = scheduler.getTrigger(triggerKey);
// 修改触发器的执行时间(例如,将执行时间改为每天上午9点)
Date newStartDate = DateBuilder.futureDate(9, IntervalUnit.HOUR);
trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
.startAt(newStartDate).build();
// 使用QuartzUtils工具类更新触发器的执行时间
quartzUtils.updateJob(null, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}