前言
有段时间没写blog了,说来惭愧,最近一直在给公司做P2P项目的服务端,但这都不是借口,高尔基曾说过(不太确定T_T),时间就像海绵里的水,只要愿意挤总是有的!所以写博客的节奏还是必须脉动回来,必须养成不断学习,不断记录,不断总结的好习惯。废话不多说,最近需要做一些服务器端的定时任务,决定使用Quartz去实现,之前也没接触过,所以就边学边做了,顺便把这个过程记录下来。
初识Quartz
首先看一下百科中对Quartz的简介:Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.2.1。
没错,Quartz是一个由Java编写的开源的任务调度框架。目前已发布的最新版本是2.2.1,下载地址:
下载完成后可以看到如下的结构图,
我们使用Quartz时需要在lib文件夹下拷出核心jar包(quartz-2.2.1.jar)添加到我们项目的classpath下,然后就可以使用Quartz的相关API了,下来我们根据官方的在线教程来快速的体验一下Quartz。但在使用之前首先我们需要了解关于Quartz的3个核心接口,分别是:Job、Trigger和Scheduler。简单的讲,Job就代表我们需要调度的任务,Trigger就是触发任务的触发器,而Scheduler就是用来绑定Job和Trigger并执行任务。首先,我们需要准备一个Job,
package com.test;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SimpleJob implements Job {
@Override
public void execute(JobExecutionContext jobCtx)
throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("Triggered. Time is " + new Date());
}
}
让我们自己的Job类实现Job接口并重写execute方法,在这个方法中去写我们需要定时调用的业务逻辑代码,这里仅仅打印了当前时间。接下来我们就可以写一个测试类去执行这个Job了,当然还缺少2个关键的对象,我们需要一个Trigger去触发Job,还需要一个Scheduler去管理Job、Trigger并执行他们,参考一下官方教程中实例化Scheduler的方法,
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
可以看到是通过SchedulerFactory去得到的Scheduler的实例,并通过start方法启动调度。接下来是实例化Job,依旧参考官方教程中的代码,
// define the job and tie it to our HelloJob class
JobDetail job = newJob(SimpleJob.class)
.withIdentity("myJob", "group1") // name "myJob", group "group1"
.build();
这里又见到了一个新的接口——JobDetail,其实Quartz在每次执行Job的时候都会重新创建一个Job实例,所以它不是直接接收一个Job的实例,而是接收一个Job的实现类,以便运行时通过newInstance方法的反射调用机制去实例化Job。在2.2.x的版本中不能直接使用构造方法,而是需要通过JobBuilder去实例化JobDetail对象,如上代码所示,通过静态导入引入了JobBuilder类并通过其静态方法newJob去实例化了JobDetail对象。现在还缺少一个Trigger去触发Job,那么继续参考教程中的代码,
// Trigger the job to run now, and then every 40 seconds
Trigger trigger = newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(5)
.repeatForever())
.build();
可以看到写法上都很类似,通过TriggerBuilder.newTrigger()方法实例化Trigger对象,其实Trigger有2个子类,分别是SimpleTrigger和CronTrigger,SimpleTrigger适用于执行一次或者固定间隔周期性执行,而CronTrigger则可以通过Cron表达式定义出各种复杂的调用方案,例如每周周三执行、每天下午6点执行等等。我这里设置的5秒调用一次,repeatForever也就是无限调用了,万事俱备只欠东风,最后通过Scheduler绑定执行Job和Trigger即可,
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
最后看一下Test类中的完整代码并运行程序:
package com.test;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class Test04 {
public static void main(String[] args) {
try {
// Grab the Scheduler instance from the Factory
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
// Job
JobDetail job = JobBuilder.newJob(SimpleJob.class)
.withIdentity("myTrigger", "group1").build();
// Trigger
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5).repeatForever())
.build();
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException se) {
se.printStackTrace();
}
}
}
总结
本篇blog算是对Quartz的入门,了解了三个关键性的基础概念:任务(Job)、触发器(Trigger)和调度器(Scheduler),在实际项目中一般我们都会在web项目中去执行一些定时任务,后序的blog会介绍Quartz整合到Spring中从而实现服务器端的定时任务以及关于Quartz的一些高级特性,敬请关注。