Quartz 是一个比较强大的任务调度工具,而且其与Spring结合尤为简单,最近因为项目的需要,简单的用到了 Quartz 的一些功能,下面对项目中使用 Quartz 的一些问题做简单的记录。
Quartz作业调度通常用两种方式实现,不与Spring集成和与Spring集成。本文先介绍下单独使用Quartz进行作业调度。作业调度主要包括三个部分,作业(job)、触发器(trigger)、调度器(scheduler)。下面我们看看如何创建一个作业调度项目。创建一个工程。把quartz-1.5.2.jar导入工程,然后创建一个作业类,让他继承Job接口,重写execute方法。代码如下所示:
package com.aostarit.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class JobTest implements Job
{
public void execute(JobExecutionContext arg0) throws JobExecutionException
{
System.out.println("this is a quartz test!");
}
}
然后创建调度类(也可以把作业类和调度类写在一个类里)。代码如下所示:
package com.aostarit.quartz;
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzTest
{
public void run() throws SchedulerException
{
// First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
// define the job and tie it to our JobTest class
JobDetail job = new JobDetail("job1", "group1", JobTest.class);
// Trigger the job to run on the next round minute
SimpleTrigger trigger =
new SimpleTrigger("trigger1", "group1", new Date(), null, 10, 1500L);
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
// Start up the scheduler
sched.start();
}
public static void main(String[] args) throws SchedulerException
{
QuartzTest test = new QuartzTest();
test.run();
}
}
在该类中,我们用到了以下的一些东西,ScheduleFactory, Scheduler, Job, JobDetail, Trigger,简单说明一下他们的用途。
Scheduler 是一个调度器,其中可以包含多个 JobDetail 和 Trigger 组成的计划任务。我们需要从调度工厂中获取一个调度器实例。
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
JobDetail描述了一个任务具体的信息,比如名称,组名等等。
JobDetail job = new JobDetail("job1", "group1", JobTest.class);
在上面的构造方法中,第一个是任务的名称,第二个是组名,第三个就是实际当任务需要执行的回调类。
Trigger顾名思义就是触发器,Quartz有个很好的想法就是分离了任务和任务执行的条件。Trigger就是控制任务执行条件的类,当Trigger认为执行条件满足的时刻,Trigger会通知相关的Job去执行。分离的好处是:
1.你可以为某个Job关联多个Trigger,其中任何一个条件满足都可以触发job执行,这样可以完成一些组合的高级触发条件
2.当Trigger失效后(比如:一个永远都不能满足的条件),你不必去声明一个新的job,代替的是你可以为job关联一个新的Trigger让job可以继续执行。
目前的Quartz实现中,存在两种Trigger,SimpleTrigger和CronTrigger,SimpleTrigger用来完成一些比如固定时间执行的任务,比如:从现在开始1分钟后等等;而CronTrigger(没错,和unix的cron进程的含意一样)用来执行calendar-like的任务,比如:每周五下午3:00,每月最后一天等等。
在我们项目中,都是一些固定时间的 Job,所以只用到了 SimpleTrigger。
SimpleTrigger trigger = new SimpleTrigger("trigger1", "group1",new Date(),null, 10, 1500L);
这个构造方法中,第一个是Trigger的名称,第二个是Trigger的组名,第三个是任务开始时间,第四个是结束时间,第五个是重复次数,最后一个是重复周期(单位是毫秒)。
然后我们需要把JobDetail和Trigger关联起来,当Trigger认为条件满足时,他就会自动执行JobTest类里的execute方法。
sched.scheduleJob(job, trigger);
最后,我们启动触发器,开始执行作业调度任务。
sched.start();
关于execute方法的参数JobExecutionContext
JobExecutionContext 就和很多Context结尾的类功能一样,提供的运行时刻的上下文环境,JobExecutionContext中有 Scheduler,JobDetail,Trigger等很多对象的引用,从而当你在execute方法内部须需要这些对象的时刻提供的便利。
在项目中,我们把需要执行的 Job 相对应的一些信息放在 JobExecutionContext 中,在 Job 执行的时候可以调用。在调度器(即上文的run方法)中加入如下代码:
jobDetail.getJobDataMap().put(userid, id);
在 Job(上文的JobTest类)中,我们可以拿到相关的 Context 信息:
jobExecutionContext.getJobDetail().getJobDataMap().getInt(userid);
注意:若是想在web工程中执行作业调度,即在启动应用服务器(weblogic、tomcat等),需要在 web.xml 里面加入以下配置:
<listener>
<listener-class>org.agilejava.scheduler.ScheduleStartListener</listener-class>
</listener>
ps:建议想学Quartz作业调度的人,可以下载quartz-1.5.2.zip包,包里除了包括Quartz的源码,还包括13个quartz的使用范例,难度也是从低到高,非常值得一看,不过加载项目的时候记得把quartz-1.5.2.jar和commons-logging-1.0.1.jar包导入工程之中。