携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情
关于quartz框架
大多数应用系统中都需要使用任务调度,基于线程的调度程序开发人员直接编写,不但存在容易出错,实现难度也比较大,所以我们选择使用 Quartz 任务调度开源框架,它提供了强大的任务调度机制,可以更快捷更方便的帮助我们完成调度操作。
Quartz 是一个由 Java 编写的开源任务调度框架,允许开发人员根据时间的间隔来调度任务,该框架实现了任务和触发器的多对多的关系,还能把多个任务与不同的触发器关联。
需要实现任务调度,首先需要明确 3 个概念:任务、触发器、调度器。
-
任务 Job
指在固定时间需要执行的工作内容。Quartz 提供了 Job 接口,来帮助我们定义一个任务。
Job 接口提供了一个 execute() 方法用于执行具体的任务,需要由 Job 的实现类去实现。
方法参数类型 JobExecutionContext 对象可以获取调度对象的上下文信息,如任务名称等。
-
触发器 Trigger
任务会在什么时间执行呢?就需要依靠触发器来指定。
Quartz 提供了 Trigger 接口,用于定义执行任务的时间规则,例如每月的第三天、每天早上 10 点、每周二、四、六下午 6 点等等规则。
Trigger 提供了两个常用的子接口:SimpleTrigger 和 CronTrigger。
-
调度器 Scheduler
有了任务和触发器(即时间规则) 后,我们还需要调度器来将二者关联起来,从而实现 “在规定的时间执行特定的任务”。Quartz 提供了 Scheduler 类来实现调度器,我们可以将任务 Job 对象和触发器 Trigger 对象注册到调度器 Scheduler 中,由调度器来决定任务和触发器的对应关系,即 Scheduler 可以将 Trigger 绑定到一个 Job 上。换句话说,调度器决定了哪个触发器定时执行哪个任务。
Quartz 框架基础程序
Quartz 框架开发准备工作
Quartz 框架相关信息,可以到官网 http://www.quartz-scheduler.org/ 下载。
下载的压缩文件进行解压,结构如下:
所有的 API 都是在 javadoc 目录下,所需的 jar 包在 lib 目录下,src 目录下是 Quartz 框架的源代码。
首先我们把 Quartz 框架开发的环境进行搭建:
创建 Quartz Maven 工程,工程名QuartzDemo01
然后在 Maven 仓库 https://mvnrepository.com ,查找需要依赖导入的 Quartz jar 包
打开 pom.xml 进行依赖导入
这样 Quartz 框架的开发环境就搭建好了。
使用 SimpleTrigger 实现任务调度
Quartz 框架的核心是任务、触发器和调度器,所有核心的接口和类都是在 org.quartz 包下,我们接下来就一步步来完成。
-
任务 Job
在 目录下创建
FirstJob.java源文件,编写任务需要做的操作。该类需要实现Job接口FirstJob实现Job接口,必须实现execute()方法,从JobExecutionContext参数中可以获取上下文信息,这里我们获取了任务名和触发器名将其打印输出,同时还输出了字符串Hello Quartz以及当前系统时间
package org.yamiya;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class FirstJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.print("任务名:" + context.getJobDetail().getKey().getName());
System.out.println(" 触发器名:" + context.getTrigger().getKey().getName());
System.out.println("Hello Quartz - " + new Date());
}
}
创建 FirstJobDetail.java 源文件,用于返回 JobDetail 实例
public class FirstJobDetail {
public static JobDetail getJobDetail(){
// 获取 JobBuilder 实例,并将任务类注入
JobBuilder jobbuilder = JobBuilder.newJob(FirstJob.class);
// 设置任务名和组名
jobbuilder.withIdentity("job1", "group1");
// 获取 JobDetail 实例
JobDetail jd = jobbuilder.build();
return jd;
}
}
JobDetail 是一个接口,需要通过 JobBuilder 类来获取它的实例进行操作,首先我们调用 JobBuilder 类中的静态方法 newJob() ,将 MyJob 加载后获取 JobBuilder 实例;获取 JobBuilder 实例后,然后我们可以通过 withIdentity() 方法设置任务名和组名,组名也可以采用默认的方式;最后我们需要调用 build() 方法返回 JobDetail 实例。上述代码为了让大家清楚知道如何获取 JobDetail 实例,所以是分步进行书写,但在实际应用中我们会采用更简洁的方式进行编写,可以这样写:
public static JobDetail getJobDetail(){
return JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
}
- 触发器 Trigger
Trigger 主要是用于触发的时间规则设置,该接口有 2 个子接口 SimpleTrigger 和 CronTrigger,本实验中我们主要是使用 SimpleTrigger
建 FirstTrigger.java 源文件,返回 SimpleTrigger 实例。
import。。
public class FirstTrigger {
public static SimpleTrigger getSimpleTrigger(){
// 获取 TriggerBuilder 实例
TriggerBuilder<Trigger> triggerbuilder = TriggerBuilder.newTrigger();
// 设置触发器名和组名
triggerbuilder.withIdentity("trigger1", "group1");
// 马上触发
triggerbuilder.startNow();
// 获取 SimpleScheduleBuilder 实例
SimpleScheduleBuilder ssbuiler = SimpleScheduleBuilder.simpleSchedule();
// 每 2 秒执行一次
ssbuiler.withIntervalInMilliseconds(2000);
// 一共执行 10 次
ssbuiler.withRepeatCount(10);
// 获取 SimpleTrigger 实例
SimpleTrigger st = triggerbuilder.withSchedule(ssbuiler).build();
return st;
}
}
上述代码中,可以看到首先通过 TriggerBuilder 类中的静态方法 newTrigger() 获取 TriggerBuilder 实例,其次通过 withIdentity() 方法设置触发器名和组名,调用 startNow() 表示立即触发;然后通过 SimpleScheduleBuilder 类中的静态方法 simpleSchedule() 获取 SimpleScheduleBuilder 实例,调用 withIntervalInMilliseconds() 和 withRepeatCount() 方法进行触发规则设置,最后通过调用 TriggerBuilder 类中的 withSchedule() 方法将 SimpleScheduleBuilder 实例注入,再调用 build() 完成 SimpleTrigger 实例获取。 同理 SimpleTrigger 我们也可以简化一些来编写,可以这样写:
public static SimpleTrigger getSimpleTrigger(){
return TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(2000)
.withRepeatCount(10)).build();
}
- 调度器 Scheduler
Scheduler 需要通过 SchedulerFactory 获取实例,而 SchedulerFactory 有两个实现类 DirectSchedulerFactory 和 StdSchedulerFactory。
创建 FirstScheduler.java 源文件,在该类中将 JobDetail 和 Trigger 进行注册完成调度工作。
import。。。
public class FirstScheduler {
public void doScheduler() {
// 通过 SchedulerFactory 获取 Scheduler 实例
SchedulerFactory factory = new StdSchedulerFactory();
try {
Scheduler scheduler = factory.getScheduler();
// 将 JobDetail 和 Trigger 注册到 Scheduler 中
scheduler.scheduleJob(FirstJobDetail.getJobDetail(), FirstTrigger.getSimpleTrigger());
// 启动调度器
scheduler.start();
System.out.println("------- Started Scheduler -----------------");
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//关闭调度器,true 表示调度完成后关闭,false 表示强行关闭
scheduler.shutdown(true);
System.out.println("------- Shutdown Complete -----------------");
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
上述代码中,我们可以看到首先通过 StdSchedulerFactory 类提供的构造器获取 SchedulerFactory 接口实例,其次通过 SchedulerFactory 调用 getScheduler() 方法获取 Scheduler 实例;然后我们就可以调用 Scheduler 接口中的 scheduleJob() 方法将 JobDetail 和 Trigger 实例注册到 Scheduler 中;最后可以调用 start() 启动调度器和 shutdown() 关闭调度器。
- test
创建一个测试类
TestQuartz并添加一个测试方法。
package org.lanqiao;
import org.junit.Test;
public class TestQuartz {
@Test
public void test(){
new FirstScheduler().doScheduler();
}
}