Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务。
Quartz可以与J2EE和J2SE应用程序相结合也可以单独使用。
RMI使用Job需要实现的任务类,每个
job都必须实现org.quartz.job接口,实现 execute() 方法,执行后完成任务。
//通过JobBulider构建一个任务实例
JobDetail jobDetail = JobBuilder.newJob(xxxJob.class);
Trigger执行任务的触发器(定时),主要包含
SimpleTrigger和CronTrigger以及自定义Trigger
//通过TriggerBuilder构建触发器实例
SimpleTrigger trigger = TriggerBuilder.newTrigger();
Scheduler任务调度器,负责基于 Trigger触发器设定的时间来执行Job任务。
//从调度工厂获取
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
Quartz提供了两种存储任务的方式:
Memory:内存方式,将任务存储到内存中,当项目重启时就会丢失,不建议生产环境使用。Jdbc:数据库方式,将任务存储到Quartz提供的固定结构的表内,项目重启任务不会丢失。Scheduler:用于定时调度程序交互的主程序接口。Scheduler调度程序:任务执行计划表,通过
scheduler.scheduleJob方法安排进执行任务,当到了预先定义的执行时间的时候触发trigger,执行任务
Job:可自定义的在未来某个时间能被调度程序执行的任务类JobDetail:使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建的JobDataMap:可以包含不限量(序列化的)的数据对象,在Job实例执行的时候,可以使用其中的数据;
JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型数据的方法
Trigger:触发器,触发执行Job任务。定义一个已被安排的任务将在什么时候执行的时间条件JobBuilder:用于声明一个任务实例,也可以定义关于该任务的详情比如任务名,组名等。通过JobBuilder声明的实例将会作为一个实际执行的任务。TriggerBuilder:触发器创建器,用于创建触发器trigger实例JobListener、TriggerListener、SchedulerListener:监听器,用于对组件的监听
springboot版本2.0之后
<!--quartz依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
springboot版本较低
<!--核心包-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<!--工具包-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>
Job接口,或者继承QuartzJobBean抽象类Job接口/**
* 任务类
* */
public class HelloJob implements Job {
static int i = 1;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("第"+i+++"次"+"Hello,Quartz!");
}
}
QuartzJobBean抽象类/**
* 任务类
* */
public class HelloJob extends QuartzJobBean {
static int i = 1;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("第"+i+++"次"+"Hello,Quartz!");
}
}
QuartzJobBean是由Spring提供,实现org.quartz.Job接口,是对Quartz内置任务接口的实现封装,源码如下:
public abstract class QuartzJobBean implements Job {
public QuartzJobBean() {
}
public final void execute(JobExecutionContext context) throws JobExecutionException {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValues(context.getScheduler().getContext());
pvs.addPropertyValues(context.getMergedJobDataMap());
bw.setPropertyValues(pvs, true);
} catch (SchedulerException var4) {
throw new JobExecutionException(var4);
}
this.executeInternal(context);
}
protected abstract void executeInternal(JobExecutionContext var1) throws JobExecutionException;
}
Job接口的优点使用QuartzJobBean来创建自定义任务时,Spring会自动扫描项目内的实现类,将每一个实现类通过反射机制创建出实例并将实例写入到IOC容器内。
直接使用Quartz时,如果自定义任务类实例不加入IOC容器,我们无法在自定义任务类注入Service
Job类/**
* 调度器
* */
public class HelloSchedulerDemo {
public static void main(String[] args) throws SchedulerException {
//1.从调度工厂获取调度器实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2. 通过JobBulider构建一个任务实例
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
//设置任务的唯一实例名和任务组的组名
.withIdentity("helloJob","helloGroup")
//构建实例
.build();
//3. 通过TriggerBuilder构建触发器实例
SimpleTrigger trigger = TriggerBuilder.newTrigger()
//设置触发器唯一实例名和触发器组名
.withIdentity("helloTrigger","helloGroup")
//执行计划,每3秒执行一次
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(3))
//立即执行
.startNow()
//构建实例
.build();
//4. 调度器绑定任务实例和触发器
scheduler.scheduleJob(jobDetail,trigger);
//5.开始定时任务
scheduler.start();
}
}

QuartzJobBean类
Job:工作任务调度接口,任务类需要实现的接口。该接口中定义了execute方法,类似JDK提供的TimeTask类的run`方法。在这里面编写任务执行的业务逻辑
Job实例在Quartz中的生命周期:每次调度器执行Job时,它在调用execute方法前会创建一个新的Job实例,当调度完成后,管理的Job对象实例将会被释放,释放的实例会被垃圾回收机制回收
JobDetail:作用是绑定Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。除此之外,JobDetail为Job实例提供了许多设置属性
Job+JobDetail模式,而不是直接使用Job
JobDetail定义任务属性,Job定义任务逻辑
任务有可能并发执行,当直接使用Job的时候,Job实例可能出现并发访问的情况。
使用Job+JobDetail模式,每次调度执行都会生成一个Job实例,这样就不用担心并发访问的问题
当
Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法
Job能通过JobExecuteContext对象访问到Quartz运行时的环境以及Job本身的明细数据