转载:http://hi.baidu.com/xulin_1027/item/1c49e7976287cfd81b49dff2
org.quartz.Job 接口
把 Quartz 作用到 Java 类上唯一要做的就是让它实现 org.quartz.Job 接口。
你的 Job 类可以实现任何其他想要的接口或继承任何需要的基类,但是它自己或是它的超类必须实现这个 Job 接口。
这个 Job 接口只定义了单个方法:
public void execute(JobExecutionContext context) throws JobExecutionException;
当 Scheduler 决定了是时候运行 Job 时,方法 execute() 就会被调用,并传递一个 JobExecutionContext 对象给这个 Job。
Quartz 加给方法 execute() 要承担的唯一合约责任就是如果在 Job 中出现严重问题时,必须抛出一个 org.quartz.JobExecutionException 异常
JobExecutionContext
当 Scheduler 调用一个 Job,一个 JobexecutionContext 传递给 execute() 方法。JobExecutionContext 对象让 Job 能访问 Quartz 运行时候环境和 Job 本身的明细数据。这就类似于在 Java Web 应用中的 servlet 访问 ServletContext 那样。通过 JobExecutionContext,Job 可访问到所处环境的所有信息,包括注册到 Scheduler 上与该 Job 相关联的 JobDetail 和 Triiger。Quartz Job 的一个非常基础的代码。PrintInfoJob 获得存储在 JobExecutionContext 中的 JobDetail 对象.
public class PrintInfoJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDetail jobDetail = context.getJobDetail();
}}
JobDetail
从以前的例子可以看的出JobDetail被加到 Scheduler 中了,而不是 job。Job 类是作为JobDetail的一部份,但是它直到 Scheduler 准备要执行它的时候才会被实例化的。Job 的实例要到该执行它们的时候才会实例化出来。每次 Job 被执行,一个新的 Job 实例会被创建。其中暗含的意思就是你的 Job 不必担心线程安全性,因为同一时刻仅有一个线程去执行给定 Job 类的实例,甚至是并发执行同一 Job 也是如此。
使用 JobDataMap 对象设定 Job 状态
你能使用org.quartz.JobDataMap来定义 Job 的状态。
JobDataMap 通过它的超类org.quartz.util.DirtyFlagMap实现了java.util.Map接口,你可以向JobDataMap中存入键/值对,那些数据对可在你的 Job 类中传递和进行访问。
这是一个向你的 Job 传送配置的信息便捷方法。通过 JobExecutionContext对象访问 JobDataMap, JobDataMap jobDataMap =context.getJobDetail().getJobDataMap();
当你获得了 JobDataMap,你可以当它是任何 map 实例一样调用它的方法。
一般的,你会自己选择一个预定义的键值来访问 JobDataMap 中的数据。
在 Quartz 1.5 中,JobDataMap 在 Trigger 级也是可用的。
它的用途类似于 Job 级的 JobDataMap,此外它还能支持应用在同一个 JobDetail上的多个 Trigger 上。
伴随着加入到 Quartz 1.5 中的这一增强特性,可以使用 JobExecutionContext 的一个新的更方便的方法获取到 Job 和 Trigger 级的并集的 map 中的值。
这个方法就是 getMergedJobDataMap(),它能够在 Job 中使用。从 Quartz 1.5 之后,使用这个方法被认为是获取 JobDataMap 最佳实践。
无状态的 Job
信息可插入到 JobDataMap 中然后被 Job 访问到。然而,对于每一次的 Job 执行,都会为特定的 Job 取用存储在某处(例如,数据库中)的值创建一个新的 JobDataMap 实例。因此,无法为两次 Job 调用之间持有那些信息,除非你使用有状态的 Job.
使用有状态的 Job
当你需要在两次 Job 执行间维护状态的话,Quartz 框架为此提供了 org.quartz.StatefulJob接口。StatefulJob接口仅仅是扩展了 Job 接口,未加入新的方法。你只需要通过使用与 Job 接口相同的execute()方法简单的实现StatefulJob接口即可。假如你有已存在的 Job 类,你所有要做的只是改变 Job 的接口为org.quartz.StatefulJob。
Job 和StatefulJob在框架中使用中存在两个关键差异。首先,JobDataMap在每次执行之后重新持久化到JobStore中。这样就确保你对 Job 数据的改变直到下次执行仍然保持着。你可以在有状态 Job 中简单的通过 map 的 put() 方法来修改 JobDataMap.已存在的任何数据会被新的数据覆盖掉。你也能对无状态的 Job 这么做,但是因为对于无状态 Job 来说,JobDataMap 不会持久化,所以数据不会保存下来。对于 Trigger 和 JobExecutionContext 上的 JobDataMap 的数据修改也是没能保存下来的。
另一个无状态和有状态 Job 重大区别就是:两个或多个有状态的 JobDetail 实例不能并发执行。说的是你创建并注册了一个有状态 JobDetail 到 Scheduler 上。你还建立了两个 Trigger 来触发这个 Job:一个每五分钟触发,另一个也是每五分钏触发。假如这两个 Trigger 试图在同一时刻触发 Job,框架是不允许这种事情发生的。第二个 Trigger 一直会被阻塞直到第一个结束。
在你使用 StatefulJob 时可要谨慎了
先前理解错误,以为是在两个JOB中可以通过有状态JOB来进行数据传递,仔细一看是“当你需要在两次 Job 执行间维护状态的话”例如以下例子:
public class SmpleJob implements StatefulJob {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
//提取上次执行的时候保存的数据
System.out.println(arg0.getJobDetail().getJobDataMap().get("Time"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//数据持久化到JobStore中
arg0.getJobDetail().getJobDataMap().put("Time", sdf.format(new Date()));
}