前言
有段时间没写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的一些高级特性,敬请关注。