通过Job,Trigger,Scheduler看Quartz2.x作业调度框架

最近使用到Quartz框架来做定时推送数据的功能的调度(注:在Java可以使用java.util.Timer和实现java.util.TimerTask接口的类做定时任务功能)。

本文主要从大的框架方面介绍Quartz的基本使用和Quartz对用户提供的扩展点JobListener等监听接口。

通常对于作业调度我们关注这三个方面的内容:作业,调度时间,由谁调度。比如:我明天去北京。这就好中,将“去北京”看做一个作业,“我”就是这个作业的调度者,而“明天”自然就是调度的时间(也可以看作是去北京这个作业的触发时间)。

由上面的小情节可以看出框架能为我们做那些事呢?分离通用的,业务无关的部分组织成为解决某一问题或特定问题的模版代码即为框架。正好,Quartz就是作业调度方面或者领域的解决方案框架。再去看“去北京”这个关键词,可以发现去北京对于实际的业务而言仅仅是一个描述性的语句,而怎么去(灰机,BBC,还是绿皮车)好像这些并没能体现出来,而这样没有体现出来的好处就是框架和业务实现完全解耦。这里就要引入几个作业调度方面的专业名词,比如Job,Trigger ,Scheduler。我们这一这么组织这三个名词,比如:一个Schedule怀揣个Trigger,这个Trigger有个玩叫Job,时不时拿出来玩两下。至于玩一下Job,Job能够产生怎样的影响对于Trigger而言并不关心,不过这里似乎使得Job与Trigger产生了耦合,因为Job属于具体业务。对于一个完备的作业调度解决方案Quartz而言这样的问题已不是问题,Quartz用JobDetail来表示Job或者表达Job,从而让具有具体业务的Job与整个框架分离。

下面通过Quartz的类图来宏观的介绍Quartz2.x的使用。

1.Job和JobDetail

具体作业业务实现Job接口,具体在作业调度中使用JobDetail,使用JobBuilder构造器来构造具体的JobDetail。两个接口+一个构造者模式的JobDetail构造器完成了具体业务Job和实际作业调度中的JobDetail分离。实际应用中只要面向JobDetail和Job两个接口编程,隐藏了具体的实现如:JobDetailImpl类。

2.Triiger(作业触发器)

对于作业触发器大多与时间,日期,调度次数,间隔时间,调度延时等有关,Quartz对作业触发做了分类并提供了TriggerBuilder。

从上图可以看到Trigger接口下有不同的触发类型,如日常间隔触发(DailyTimeIntervalTriggerImpl),基于日历的触发,Cron出发,简单的触发。同样TriggerBuilder提供了构建Trigger的简便方式,使用者可以通过其来设置不同的属性信息构建具体的Trigger实现的实例。

3.作业调度器Scheduler

Quartz提供了不同类型的调度器实现,一般我们使用StdScheduler即可满足需要,如涉及到分布式或者远程方法调用则可以选择其它两种合适的实现。

4.Quartz提供的扩展之Listener

Quartz提供了各种Listener接口为用户观察作业,触发器,作业调度器执行过程提供了扩展点。

Scheduler对象具有ListenerManager的属性,ListenerManager对象用来管理TriggerListener,JobListener,SchedulerListener的实现,监听关系(比如:指定全局Job监听,指定特定的Job监听等),具体使用参见下文。

下面提供一组Quartz使用的示例代码:

package secondriver.springsubway.demo.job;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

public class TestJobListener {

    public static Scheduler scheduler;

    @BeforeClass
    public static void setBeforeClass() throws SchedulerException {
        StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
        scheduler = schedulerFactory.getScheduler();
        scheduler.start();
    }

    @AfterClass
    public static void setAfterClass() throws SchedulerException {
        if (scheduler.isStarted()) {
            scheduler.shutdown(true);
        }
    }

    //Prepared for Test

    /**
     * 使用Builder模式构建JobDetail实例
     * @return
     */
    public static JobDetail getJobDetail() {
        return JobBuilder.newJob(MyJob.class).withDescription("MyJobDetail")
                .withIdentity("myJob", "myJobGroup")
                .build();
    }

    /**
     * 使用Builder模式构建Trigger实例
     * @return
     */
    public static Trigger getTrigger() {
        return TriggerBuilder.newTrigger().withDescription("MyTrigger").withIdentity("myTrigger",
                "myTriggerGroup")
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(3))
                .startNow().build();
    }

    @Test
    public void testOne() throws SchedulerException {
        JobDetail jobDetail = getJobDetail();
        Trigger trigger = getTrigger();

        scheduler.getListenerManager().addJobListener(new MyJobListener());
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener());

        scheduler.scheduleJob(jobDetail, trigger);

    }

    @Test
    public void testTwo() throws SchedulerException {
        JobDetail jobDetail = getJobDetail();
        Trigger trigger = getTrigger();

        /**
         * 为指定jobGrup添加JobListener
         */
        scheduler.getListenerManager().addJobListener(new MyJobListener(), GroupMatcher.jobGroupEquals("myJobGroup"));
        /**
         * 为指定triggerGroup添加TriggerListener
         */
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(), GroupMatcher.triggerGroupEquals
                ("myTriggerGroup"));

        scheduler.scheduleJob(jobDetail, trigger);
    }

    @Test
    public void testThree() throws SchedulerException, InterruptedException {
        JobDetail jobDetail = getJobDetail();

        //非持久化Job无关联Trigger添加到Scheduler需要使用addJob第三个参数storeNonDurableWhileAwaitingScheduling为true
        scheduler.addJob(jobDetail, false, true);

        //JobDetail 1<->* Trigger
        Trigger trigger1 = TriggerBuilder.newTrigger().forJob(jobDetail)
                .startNow().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever()).build();

        Trigger trigger2 = TriggerBuilder.newTrigger().forJob(jobDetail)
                .startNow().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();

        scheduler.scheduleJob(trigger1);
        scheduler.scheduleJob(trigger2);

        Thread.sleep(10000);
    }

    /**
     * 具体业务实现类,实现Job接口的execute方法即可
     */
    public static class MyJob implements Job {

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            System.out.println("MyJob " + this.getClass().getCanonicalName());
        }
    }

    /**
     * JobListener实现
     * <p/>
     * JobListener方法执行顺序
     * <p/>
     * 如果TriigerListener的vetoJobExecution返回true
     * triggerFired -> vetoJobExecution ->jobExecutionVetoed
     * <p/>
     * 如果TiggerListener的vetoJobExecution返回false
     * triggerFired -> vetoJobExecution ->jobToBeExecuted -> [Job execute] -> jobWasExecuted
     * ->[triggerMisfired|triggerComplete]
     */
    public static class MyJobListener implements JobListener {
        @Override
        public String getName() {
            return "MyJobListener";
        }

        @Override
        public void jobToBeExecuted(JobExecutionContext context) {
            System.out.println("jobToBeExecuted:" + context.getJobDetail().getDescription());
        }

        @Override
        public void jobExecutionVetoed(JobExecutionContext context) {
            System.out.println("jobExecutionVetoed:" + context.getJobDetail().getDescription());
        }

        @Override
        public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
            System.out.println("jobWasExecuted:" + context.getJobDetail().getDescription());
        }
    }

    /**
     * TriggerListener实现
     */
    public static class MyTriggerListener implements TriggerListener {

        @Override
        public String getName() {
            return "MyTriggerListener";
        }

        @Override
        public void triggerFired(Trigger trigger, JobExecutionContext context) {
            System.out.println("triggerFired:" + trigger.getDescription());
        }

        @Override
        public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
            System.out.println("vetoJobExecution:" + trigger.getDescription());
            return false;

            /**
             return:false
             triggerFired:MyTrigger
             vetoJobExecution:MyTrigger
             jobToBeExecuted:MyJobDetail
             MyJob secondriver.quartz.TestJobListener.MyJob
             jobWasExecuted:MyJobDetail
             triggerComplete:MyTrigger
             */
            /**
             return:true
             triggerFired:MyTrigger
             vetoJobExecution:MyTrigger
             jobExecutionVetoed:MyJobDetail
             */
        }

        @Override
        public void triggerMisfired(Trigger trigger) {
            System.out.println("triggerMisfired:" + trigger.getDescription());
        }

        @Override
        public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
            System.out.println("triggerComplete:" + trigger.getDescription());
        }
    }
}

上述代码依赖Quartz框架的Maven配置:

<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <version>2.2.1</version>
   <artifactId>quartz</artifactId>
</dependency>

Quartz在Java应用作业调度方面提供了非常完备的实现,本文通过三个作业调度方面的关键词和Quartz的用户扩展Listener简要介绍了Quartz的使用,更多内容可以查看Quartz用户手册或者源代码。

时间: 2024-10-09 05:27:20

通过Job,Trigger,Scheduler看Quartz2.x作业调度框架的相关文章

关于Quartz.NET作业调度框架的一点小小的封装,实现伪AOP写LOG功能

Quartz.NET是一个非常强大的作业调度框架,适用于各种定时执行的业务处理等,类似于WINDOWS自带的任务计划程序,其中运用Cron表达式来实现各种定时触发条件是我认为最为惊喜的地方. Quartz.NET主要用到下面几个类: IScheduler --调度器 IJobDetail --作业任务 ITrigger --触发器 如果我们自己采用Timer来写类似的定时执行任务程序的话,相应的我们应该有:(以下均为设想,目的是让大家搞清楚Quartz.NET上面三个接口的关系) Schedul

Quartz.NET作业调度框架详解(转载)

Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而 创建简单的或复杂的调度.它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等. 你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行.一个自动执行而无须干预的任务在执行过程 中如果发生一个严重错

Quartz.NET作业调度框架详解

本文来自:http://www.cnblogs.com/leeolevis/archive/2010/12/08/1900050.html Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等. 你曾经需要应用执行一个

Quartz.NET 2.0 作业调度框架使用

Quartz.NET是一个开源的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等. 完成一个Quartz调度需要:调度器(IScheduler).任务(JobDetail).触发器(Trigger) 无需配置文件代码如下: using Qua

作业调度框架 Quartz.NET 2.0 StepByStep

注:目前网上诸多介绍Quartz.net的文章,甚至Quartz.net官网上的Tutorial都是1.0版本的,而这个项目在2.0版本对项目进行了比较大规模的修改,使得原有的很多例子都不能运行,故写此文.由于本人是边学边用,加之技术写作水平皆有限,错误自然难免,望轻拍,我将不定时更新完善此贴,希望能为需要的朋友提供帮助. 1. 项目介绍 现今的系统,业务数据是越来越大,传统的同步处理方式有时候已经不能满足用户需求,定时后台服务这种异步数据处理形式则逐渐被大家接受.相信大家在平时的工作中也经常遇

Quartz作业调度框架

Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.本系统结合通过 Spring 来集成 Quartz . Quartz  下载地址 : http://grepcode.com/snapshot/repo1.maven.org/maven2/org.quartz-scheduler/quartz/1.7.3 首先下载包 :quartz-1.7.3.ja

Quartz.net开源作业调度框架使用详解(转)

前言 quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本.支持 cron-like表达式,集群,数据库.功能性能强大更不用说. 下载项目文档官网:http://www.quartz-scheduler.net/ 项目中需引用:Common.Logging.dll , Common.Logging.Core.dll , Quartz.dll 下面给大家分解下我最近做的关于计划调度的一个小项目,来辅助理解quartz.n

Quartz.net开源作业调度框架使用详解

前言 quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本.支持 cron-like表达式,集群,数据库.功能性能强大更不用说. 下载项目文档官网:http://www.quartz-scheduler.net/ 项目中需引用:Common.Logging.dll , Common.Logging.Core.dll , Quartz.dll 下面给大家分解下我最近做的关于计划调度的一个小项目,来辅助理解quartz.n

[转载] Quartz作业调度框架

转载自http://yangpanwww.iteye.com/blog/797563 Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.本系统结合通过 Spring 来集成 Quartz . Quartz  下载地址 : http://grepcode.com/snapshot/repo1.maven.org/maven2/org.quartz-sc