quartz教程

本文转自:http://blog.csdn.net/huihuimimi17/article/details/8215779 感谢作者 

什么是Quartz


Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。简单地创建一个org.quarz.Job接口的Java类,Job接口包含唯一的方法:

    public void execute(JobExecutionContext context) throws JobExecutionException;

在Job接口实现类里面,添加需要的逻辑到execute()方法中。配置好Job实现类并设定好调度时间表,Quartz就会自动在设定的时间调度作业执行execute()。

整合了Quartz的应用程序可以重用不同事件的作业,还可以为一个事件组合多个作业。Quartz通过属性文件来配置JDBC事务的数据源、全局作业、触发器侦听器、插件、线程池等等。

Quartz是由James House创建并最初于2001年春天被加入sourceforge工程。接下来的几年里,有很多的新特性和版本出现,但是直到项目迁移到新的站点并成为OpenSymphony项目家族的一员,才开始真正启动并受到也有的关注。

目前的版本已经是2.0以上,v2.x相对于v1.x有很多新特性出现,并有很多的改动,具体参见Quartz官网上说明。这里介绍的仍然是v1.x(v1.8.6)。

 "Hello, Quartz"


配置环境:

1. 下载Quartz

2. 阅读Readme.txt,了解每个jar包的作用,将quartz.jar包和lib/下的几个jar包、以及相关依赖的jar包放在工程的classpath中

先来看一个简单的Quartz应用,让它每隔5s打印"Hello, Quartz",打印10次。

代码清单1:创建任务

import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloQuartzJob implements Job {

public void execute(JobExecutionContext context) 
            throws JobExecutionException {
        System.out.println("Hello, Quartz! - executing its JOB at "+ 
            new Date() + " by " + context.getTrigger().getName());
    }
}

为了调度此任务执行,需要先得到一个Schedule实例,然后创建一个包含任务信息的JobDetail,最后创建一个Trigger管理任务的执行。

代码清单2:调度任务

import java.sql.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 HelloQuartzScheduling {

public static void main(String[] args)throws SchedulerException {

SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

JobDetail jobDetail = new JobDetail("helloQuartzJob", 
                Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);

SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger", 
                Scheduler.DEFAULT_GROUP);

simpleTrigger.setStartTime(new Date(System.currentTimeMillis()));
        simpleTrigger.setRepeatInterval(5000);
        simpleTrigger.setRepeatCount(10);

scheduler.scheduleJob(jobDetail, simpleTrigger);

scheduler.start();
    }

}

运行结果:

可以看到,其实它执行了11次。此处没有配置log4j.properties属性文件。

CronTrigger类


Quartz有两大触发器,除了上面使用的SimpleTrigger外,就是CronTrigger。CronTrigger能够提供复杂的触发器表达式的支持。CronTrigger是基于Unix Cron守护进程,它是一个调度程序,支持简单而强大的触发器语法。

使用CronTrigger主要的是要掌握Cron表达式。Cron表达式包含6个必要组件和一个可选组件,如下表所示。


位置


含义


允许的特殊字符


1


秒(0~59)


, -  *  /


2


分(0~59)


, -  *  /


3


小时(0~24)


, -  *  /


4


日期(1~31)


, -  *  /  ?  L  W  C


5


月(JAN~DEC或1~12)


, -  *  /


6


星期(SUN~SAT或1~7)


, -  *  /  ?  L  C  #


7


年(可选,1970~2099),若为空,表示全部时间范围


, -  *  /

特殊字符的含义,见下表。


特殊字符


说明


*


通配符,任意值


?


无特定值。通常和其他指定的值一起使用,表示必须显示该值但不能检查


-


范围。e.g.小时部分10-12表示10:00,11:00, 12:00


,


列分隔符。可以让你指定一系列的值。e.g.在星期域中指定MON、TUE和WED


/


增量。表示一个值的增量,e.g.分钟域中0/1表示从0开始,每次增加1min


L


表示Last。它在日期和星期域中表示有所不同。在日期域中,表示这个月的最后一天,而在星期域中,它永远是7(星期六)。当你希望使用星期中某一天时,L字符非常有用。e.g.星期域中6L表示每一个月的最后一个星期五


W


在本月内离当天最近的工作日触发,所谓的最近工作日,即当天到工作日的前后最短距离,如果当天即为工作日,则距离是0;所谓本月内指的是不能跨月取到最近工作日,即使前/后月份的最后一天/第一天确实满足最近工作日。e.g. LW表示本月的最后一个工作日触发,W强烈依赖月份。


#


表示该月的第几个星期,e.g. 1#2表示每一个月的第一个星期一


C


日历值。日期值是根据一个给定的日历计算出来的。在日期域中给定一个20C将在20日(日历包括20日)或20日后日历中包含的第一天(不包括20日)激活触发器。例如在一个星期域中使用6C表示日历中星期五(日历包括星期五)或者第一天(日历不包括星期五)

Cron表达式举例:

"30 * * * * ?" 每半分钟触发任务

"30 10 * * * ?" 每小时的10分30秒触发任务

"30 10 1 * * ?" 每天1点10分30秒触发任务

"30 10 1 20 * ?" 每月20号1点10分30秒触发任务

"30 10 1 20 10 ? *" 每年10月20号1点10分30秒触发任务

"30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务

"30 10 1 ? 10 * 2011" 2011年10月每天1点10分30秒触发任务

"30 10 1 ? 10 SUN 2011" 2011年10月每周日1点10分30秒触发任务

"15,30,45 * * * * ?" 每15秒,30秒,45秒时触发任务

"15-45 * * * * ?" 15到45秒内,每秒都触发任务

"15/5 * * * * ?" 每分钟的每15秒开始触发,每隔5秒触发一次

"15-30/5 * * * * ?" 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次

"0 0/3 * * * ?" 每小时的第0分0秒开始,每三分钟触发一次

"0 15 10 ? * MON-FRI" 星期一到星期五的10点15分0秒触发任务

"0 15 10 L * ?" 每个月最后一天的10点15分0秒触发任务

"0 15 10 LW * ?" 每个月最后一个工作日的10点15分0秒触发任务

"0 15 10 ? * 5L" 每个月最后一个星期四的10点15分0秒触发任务

"0 15 10 ? * 5#3" 每个月第三周的星期四的10点15分0秒触发任务

将上面HelloQuartz例子中SimpleTrigger换成CronTrigger,代码如下。

代码清单3:CronTrigger调度器

import java.text.ParseException;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

public class HelloQuartzScheduling {

public static void main(String[] args) 
        throws SchedulerException, ParseException {

SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

JobDetail jobDetail = new JobDetail("helloQuartzJob", 
                Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);

String cronExpression = "30/5 * * * * ?"; // 每分钟的30s起,每5s触发任务        
        CronTrigger cronTrigger = new CronTrigger("cronTrigger", 
                Scheduler.DEFAULT_GROUP, cronExpression);

scheduler.scheduleJob(jobDetail, cronTrigger);

scheduler.start();
    }

}

运行结果:

CronTrigger使用HolidayCalendar类可以排除某一段时间,比如说国庆节不执行调度任务,代码示例如下:

代码清单4:HolidayCalendar的使用

import java.text.ParseException;
import java.util.Calendar;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.HolidayCalendar;

public class HelloQuartzScheduling {

public static void main(String[] args) 
        throws SchedulerException, ParseException {

SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

JobDetail jobDetail = new JobDetail("helloQuartzJob", 
                Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);

Calendar cal = Calendar.getInstance();
        cal.set(2012, Calendar.OCTOBER, 1); // 国庆节

HolidayCalendar holidayCal = new HolidayCalendar();
        holidayCal.addExcludedDate(cal.getTime()); // 排除该日期

// addCalendar(String calName, Calendar calendar, 
        //             boolean replace, boolean updateTriggers)
        scheduler.addCalendar("calendar", holidayCal, true, false);

String cronExpression = "30/5 * * * * ?"; // 每5s触发任务        
        CronTrigger cronTrigger = new CronTrigger("cronTrigger", 
                Scheduler.DEFAULT_GROUP, cronExpression);

cronTrigger.setCalendarName("calendar");

scheduler.scheduleJob(jobDetail, cronTrigger);

scheduler.start();
    }

}

 JobStore: 任务持久化


Quartz支持任务持久化,这可以让你在运行时增加任务或者对现存的任务进行修改,并为后续任务的执行持久化这些变更和增加的部分。中心概念是JobStore接口。默认的是RAMJobStore。

配置文件


上述没有用到任何的配置文件。Quartz支持配置文件,它的好处是比编写代码简单,且修改后不需要重新编译源码。

>> 配置quartz.properties特性文件

quartz.properties文件定义了Quartz应用运行时行为,还包含了许多能控制Quartz运转的属性。它应放在工程的classpath中。

代码清单5:quartz.properties

#============================================================================  
# Configure Main Scheduler Properties  
#============================================================================

# 实例名
org.quartz.scheduler.instanceName = QuartzScheduler 
# 实例ID
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# 线程个数
org.quartz.threadPool.threadCount = 3
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#============================================================================
# Configure Plugins 
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
# org.quartz.plugins.xml.JobInitializationPlugin是Quartz自带的插件,
# 默认时,这个插件会在 classpath 中搜索名为 quartz_jobs.xml 
# 的文件并从中加载 Job 和 Trigger 信息
# v1.8之前用JobInitializationPlugin
#org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz_jobs.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval =10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

# 关闭quartz新版本检测功能
org.quartz.scheduler.skipUpdateCheck = true

>> 配置quartz_jobs.xml文件

在配置quart_jobs.xml时,遇到一个问题:

Exception in thread "main" org.quartz.SchedulerException: SchedulerPlugin class‘org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin;‘ couldnot be instantiated.

因为quartz从版本1.8开始,配置文件有所改动,以前quartz自带的插件是JobInitializationPlugin,而1.8中是XMLSchedulingDataProcessorPlugin. xml schema亦有所改变,难道是改变后配置不对?错误提示是插件类找不到,jar包也都加入到工程了啊。最后终于发现,在quartz.properties特性文件中配置插件行最后多打了个分号。原来是一个多余的分号引发的错误!

下面是新的xml配置文件格式示例。

代码清单6:quartz_jobs.xml格式 

<?xmlversion="1.0"encoding="UTF-8"?>

<job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.ogr/xml/job_scheduling_data_1_8.xsd"

version="1.8">

<pre-processing-commands>

<!--在执行作业和触犯器之前执行的命令-->

<delete-jobs-in-group>*</delete-jobs-in-group>

<!--删除标示组中的所有作业,如果是“*”,则删除所有组中的作业,同时也会删除与作业有关的触犯器 -->

<delete-triggers-in-group>*</delete-triggers-in-group>

<!--删除标示组中的所有触犯器,如果是“*”,则删除所有组中的触发器 -->

<delete-job>

<!--删除指定的作业,同时也会删除与它关联的触犯器 -->

<name></name>

<group></group>

</delete-job>

<delete-trigger>

<!--删除指定的触犯器 -->

<name></name>

<group></group>

</delete-trigger>

</pre-processing-commands>

<processing-directives>

<!--在计划作业和触发器是应遵循的命令和原则 -->

<overwrite-existing-data>true or false</overwrite-existing-data>

<!--是否复写已经存在的任务计划数据,如果为false并且ingore-duplicates非false,那么文件中同名的触发器或作业将会继续存在,则会产生错误-->

<ignore-duplicates>true or false</ignore-duplicates>

<!--如果为true,计划中的任何同名的作业/触发器将会被忽略,不会产生错误-->

</processing-directives>

<schedule>

<job>

<name>JobName</name>

<group>JobGroup</group>

<description></description>

<job-class></job-class>

<job-listener-ref></job-listener-ref>

<!-- volatility,durability,recover必须按顺序设定 -->

<volatility></volatility>

<durability></durability>

<recover></recover>

<job-data-map>

<!-- entry可以设定多个-->

<entry>

<key></key>

<value></value>

</entry>

</job-data-map>

</job>

<trigger>

<!-- Trigger分为simple,cron,date-interval三种类型,一个trigger中只能指定一种类型-->

<simple>

<name></name>

<group></group>

<description></description>

<job-name></job-name>

<job-group></job-group>

<calendar-name></calendar-name>

<volatility></volatility>

<job-data-map>

<entry>

<key></key>

<value></value>

</entry>

</job-data-map>

<start-time></start-time>

<end-time></end-time>

<misfire-instruction></misfire-instruction>

<repeat-count></repeat-count>

<repeat-interval></repeat-interval>

</simple>

<cron>

<name></name>

<group></group>

<description></description>

<job-name></job-name>

<job-group></job-group>

<calendar-name></calendar-name>

<volatility></volatility>

<job-data-map>

<entry>

<key></key>

<value></value>

</entry>

</job-data-map>

<start-time></start-time>

<end-time></end-time>

<misfire-instruction></misfire-instruction>

<cron-expression></cron-expression>

<time-zone></time-zone>

</cron>

<date-interval>

<name></name>

<group></group>

<description></description>

<job-name></job-name>

<job-group></job-group>

<calendar-name></calendar-name>

<volatility></volatility>

<job-data-map>

<entry>

<key></key>

<value></value>

</entry>

</job-data-map>

<start-time></start-time>

<end-time></end-time>

<misfire-instruction></misfire-instruction>

<repeat-interval></repeat-interval>

<repeat-interval-unit></repeat-interval-unit>

</date-interval>

</trigger>

</schedule>

</job-scheduling-data>

代码清单7:quartz_jobs.xml示例

<?xmlversion="1.0"encoding="UTF-8"?>

<job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"

version="1.8">

<pre-processing-commands>

<delete-jobs-in-group>*</delete-jobs-in-group> <!-- clear all jobs in scheduler -->

<delete-triggers-in-group>*</delete-triggers-in-group><!-- clear all triggers in scheduler -->

</pre-processing-commands>

<processing-directives>

<overwrite-existing-data>true</overwrite-existing-data>

<ignore-duplicates>false</ignore-duplicates>

</processing-directives>

<schedule>

<job>

<name>helloQuartzJob</name>

<group>DEFAULT</group>

<description>简单的quartz使用</description>

<job-class>HelloQuartzJob</job-class>

<volatility>false</volatility>

<durability>true</durability>

<recover>false</recover>

</job>

<trigger>

<cron>

<name>trigger</name>

<group>DEFAULT</group>

<job-name>helloQuartzJob</job-name>

<job-group>DEFAULT</job-group>

<cron-expression>30/5 * * * * ?</cron-expression>

</cron>

</trigger>

</schedule>

</job-scheduling-data>

代码清单8:Quartz任务调度

public class HelloQuartzScheduling {
    
    public static void main(String[] args) 
       throws SchedulerException, ParseException {
       
       SchedulerFactory schedulerFactory = new StdSchedulerFactory();
       Scheduler scheduler = schedulerFactory.getScheduler();
       
       scheduler.start();              
    }   
}

这里遇到个问题,提示错误:

Exception in thread "main" Java.lang.NoClassDefFoundError: javax/transaction/UserTransaction

是由于缺少jta.jar,google出的结果是在quartz发行包的/lib中有此jar包,但是在1.8中没有找到。下载quartz 1.7中,也没有找到,因此,在网上搜一个jta.jar包放置过程classpath中,然后编译运行,ok.

时间: 2024-07-28 20:37:48

quartz教程的相关文章

Quartz教程五:SimpleTrigger

原文链接 | 译文链接 | 翻译:nkcoder 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣研究源码的同学,可以参考我对quartz-core源码的注释(进行中). SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次.比如,你有一个trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或

Quartz教程四:Trigger

原文链接 | 译文链接 | 翻译:nkcoder 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣研究源码的同学,可以参考我对quartz-core源码的注释(进行中). 与job一样,trigger也很容易使用,但是还有一些扩展选项需要理解,以便更好地使用quartz.trigger也有很多类型,可以根据实际需要来选择. 最常用的两种trigger会分别在教程五:SimpleTrigger和教

Quartz教程二:API,Job和Trigger

原文链接 | 译文链接 | 翻译:nkcoder | 校对:方腾飞 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣研究源码的同学,可以参考我对quartz-core源码的注释(进行中). Quartz API Quartz API核心接口有: Scheduler – 与scheduler交互的主要API: Job – 你通过scheduler执行任务,你的任务类需要实现的接口: JobDeta

Java任务调度框架Quartz教程实例

介绍: Quartz框架是一个全功能.开源的任务调度服务,可以集成几乎任何的java应用程序-从小的单片机系统到大型的电子商务系统.Quartz可以执行上千上万的任务调度. 核心概念 Quartz核心的概念:scheduler任务调度.Job任务.Trigger触发器.JobDetail任务细节 转自这篇文章对于Quartz定时器写的不错: http://blog.csdn.net/yuebinghaoyuan/article/details/9045471

Quartz学习总结

参考链接: 深入解读Quartz的原理:http://lavasoft.blog.51cto.com/62575/181907/ Java任务调度框架Quartz教程实例:http://blog.csdn.net/yuebinghaoyuan/article/details/9045471 最新quartz框架介绍:http://wenku.baidu.com/link?url=gSz5B1yZiD53xIsINzzhItRLu3SdoUnyBtITzmjswDS2p6IhUv8ps-AYak7

Quartz 框架 教程(中文版)2.2.x

Quartz 框架 教程(中文版)2.2.x 之第一课 开始使用Quartz框架 Quartz 框架 教程(中文版)2.2.x 之第二课 Quartz API,Jobs和Triggers简介 Quartz 框架 教程(中文版)2.2.x 之第三课 更多关于Jobs和JobDetails Quartz 框架 教程(中文版)2.2.x 之第四课 更多关于Triggers Quartz 框架 教程(中文版)2.2.x 之第五课 SimpleTrigger Quartz 框架 教程(中文版)2.2.x

Quartz.NET教程:(01) 使用Quartz

使用调度器 (scheduler) 之前要先用 ISchedulerFactory 的一个实现来实例化调度器(scheduler).一旦调度器实例化完成,则它可以被启动.置于备用模式或者关闭.需要注意的是一旦调度器被关闭,只有重新实例化后才能重新启动它.调度器启动前或者触发器处于暂停状态时,触发器都不会被触发(即任务不会执行). 下列代码片段演示了实例化并启动一个调度器,并且安排了一个任务以便执行: 使用 Quartz.NET // construct a scheduler factory I

[译]Quartz.Net 框架 教程(中文版)2.2.x 之第三课 更多关于Jobs和JobDetails

第三课 更多关于Jobs和JobDetails 在这二课我们已经学习到,Jobs接口非常容易实现,只有一个execute方法.我们需要再学习一些知识去理解jobs的本质,Job接口的execute方法以及JobDetails接口. 当你实现Job接口类,Quartz需要你提供job实例的各种参数,Job接口实现类中的代码才知道如何去完成指定类型Job的具体工作.这个过程是通过JobDetail类来完成的,该类会在下一个章节作简要介绍.        JobDetail的实例是调用JobBuild

[译]Quartz.NET 框架 教程(中文版)2.2.x 之第四课 更多关于Triggers

第四课 更多关于Triggers 跟作业任务类似,触发器也非常容易使用,但是在你能够充分掌握Quartz之前,你需要知道并理解许多触发器的客户化的参数.前面已经提到过,有许多不同类型的触发器供你选择,适用不同的调度需求. 你将会在第五课 Simple Trigger和第六课 Triggers学到这两种常用的触发器类型. 触发器通用属性 所有类型的触发器都有TriggerKey属性去跟踪触发器标识,除了这一个事实之外,还有许多其他的属性,对所有触发器类型都适用.这些通用属性在创建触发器定义时通过T