Quartz API

  • Scheduler - 与调度程序交互的主要API。
  • Job - 由希望由调度程序执行的组件实现的接口。
  • JobDetail - 用于定义作业的实例。
  • Trigger(即触发器) - 定义执行给定作业的计划的组件。
  • JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
  • TriggerBuilder - 用于定义/构建触发器实例。

Job与JobDetail

你定义了一个实现Job接口的类,这个类仅仅表明该job需要完成什么类型的任务,除此之外,Quartz还需要知道该Job实例所包含的属性;这将由JobDetail类来完成。

  public class HelloJob implements Job {

    public HelloJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      System.err.println("Hello!  HelloJob is executing.");
    }
  }
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();

这里有个问题就是我需要在HelloJob类定义几个属性,用于数据处理,但是这里每次当scheduler执行job时,在调用execute(…)方法之前会创建该类的一个新的实例,原来的属性的值就用不到了,这里quartz给我们提供了JobDataMap用作处理

JobDataMap

JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。 

  JobDetail job = newJob(DumbJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .usingJobData("jobSays", "Hello World!")
      .usingJobData("myFloatValue", 3.141f)
      .build();
public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }

JobExecutionContext中的JobDataMap为我们提供了很多的便利。它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值。

JobKey key = context.getJobDetail().getKey();
JobDataMap dataMap = context.getMergedJobDataMap();  

也可以实现自动注入,只需在实现Job接口的类中添加属性及其getter,setter方法即可

 Job实例

你可以只创建一个job类的实现,然后创建多个与该job关联的JobDetail实例,每一个实例都有自己的属性集和JobDataMap,最后,将所有的实例都加到scheduler中。

Job状态与并发 

  • @DisallowConcurrentExecution:将该注解加到job类上,告诉Quartz不要并发地执行同一个job定义(这里指特定的job类)的多个实例。请注意这里的用词。拿前一小节的例子来说,如果“SalesReportJob”类上有该注解,则同一时刻仅允许执行一个“SalesReportForJoe”实例,但可以并发地执行“SalesReportForMike”类的一个实例。所以该限制是针对JobDetail的,而不是job类的。但是我们认为(在设计Quartz的时候)应该将该注解放在job类上,因为job类的改变经常会导致其行为发生变化。
  • @PersistJobDataAfterExecution:将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该job(即JobDetail)在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据。
  • @DisallowConcurrentExecution,尽管注解是加在job类上的,但其限制作用是针对job实例的,而不是job类的。由job类来承载注解,是因为job类的内容经常会影响其行为状态(比如,job类的execute方法需要显式地“理解”其”状态“)。
  • 如果你使用了@PersistJobDataAfterExecution注解,我们强烈建议你同时使用@DisallowConcurrentExecution注解,因为当同一个job(JobDetail)的两个实例被并发执行时,由于竞争,JobDataMap中存储的数据很可能是不确定的。

Trigger 

触发器,用来设置job的触发时间,频次的。主要有两种Trigger:Simple Trigger,Cron Trigger

Simple Trigger

释义:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次

特点:开始时间、结束时间、重复次数以及重复的间隔

trigger = newTrigger()
        .withIdentity("trigger3", "group1")
        .startAt(myTimeToStartFiring)  // if a start time is not given (if this line were omitted), "now" is implied
        .withSchedule(simpleSchedule()
            .withIntervalInSeconds(10)
            .withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
        .forJob(myJob) // identify job with handle to its JobDetail itself                   
        .build();

Cron Trigger

释义:基于日历的概念,进行指定间隔进行重新启动的作业启动计划

特点:cron表达式

字段名                               允许的值                         允许的特殊字符 

Seconds(                   0-59                                   , - * / 

Minutes(                    0-59                                    , - * / 

Hours(小时                    0-23                                   , - * / 

Day-of-Month(          1-31                                    , - * ? / L W C

Month(                     1-12 or JAN-DEC                , - * / 

Day-of-Week(周几        1-7 or SUN-SAT                 , - * ? / L C # 

Year (年(可选字段)         empty                                1970-2099 , - * /

特殊字符含义:

* :代表所有可能的值。因此,“*”在Month中表示每个月,在Day-of-Month中表示每天,在Hours表示每小时

- :表示指定范围。

, :表示列出枚举值。例如:在Minutes子表达式中,“5,20”表示在5分钟和20分钟触发。

/ :被用于指定增量。例如:在Minutes子表达式中,“0/15”表示从0分钟开始,每15分钟执行一次。"3/20"表示从第三分钟开始,每20分钟执行一次。和"3,23,43"(表示第3,23,43分钟触发)的含义一样。

:用在Day-of-Month和Day-of-Week中,指“没有具体的值”。当两个子表达式其中一个被指定了值以后,为了避免冲突,需要将另外一个的值设为“?”。例如:想在每月20日触发调度,不管20号是星期几,只能用如下写法:0 0 0 20 * ?,其中最后以为只能用“?”,而不能用“*”。

:用在day-of-month和day-of-week字串中。它是单词“last”的缩写。它在两个子表达式中的含义是不同的。

在day-of-month中,“L”表示一个月的最后一天,一月31号,3月30号。

在day-of-week中,“L”表示一个星期的最后一天,也就是“7”或者“SAT”

如果“L”前有具体内容,它就有其他的含义了。例如:“6L”表示这个月的倒数第六天。“FRIL”表示这个月的最后一个星期五。

注意:在使用“L”参数时,不要指定列表或者范围,这样会出现问题。

:“Weekday”的缩写。只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第 16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在 day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日,即最后一个星期五。

:只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3" or "FRI#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
    .forJob("myJob", "group1")
    .build();

TriggerListeners和JobListeners和SchedulerListeners

TriggerListeners接收到与触发器(trigger)相关的事件,JobListeners 接收与jobs相关的事件。与触发相关的事件包括:触发器触发,触发失灵,并触发完成(触发器关闭的作业完成)。

SchedulerListeners接收与Scheduler相关的事件。与计划程序相关的事件包括:添加job/触发器,删除job/触发器,调度程序中的严重错误,关闭调度程序的通知等

Job Stores

 JobStore负责跟踪您提供给调度程序的所有“工作数据”:jobs,triggers,日历等

RAMJobStore

RAMJobStore是使用最简单的JobStore,它也是性能最高的(在CPU时间方面)。RAMJobStore以其明显的方式获取其名称:它将其所有数据保存在RAM中。这就是为什么它是闪电般快的,也是为什么这么简单的配置。缺点是当您的应用程序结束(或崩溃)时,所有调度信息都将丢失 - 这意味着RAMJobStore无法履行作业和triggers上的“非易失性”设置。对于某些应用程序,这是可以接受的 - 甚至是所需的行为,但对于其他应用程序,这可能是灾难性的。

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

 JDBC JobStore

JDBCJobStore也被恰当地命名 - 它通过JDBC将其所有数据保存在数据库中。因此,配置比RAMJobStore要复杂一点,而且也不是那么快。但是,性能下降并不是很糟糕,特别是如果您在主键上构建具有索引的数据库表。

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

 注意表结构可以参考这个https://github.com/quartz-scheduler/quartz/tree/quartz-2.1.7/docs/dbTables

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐