继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Quartz教程(二)Job and JobDetails

慕设计6931647
关注TA
已关注
手记 54
粉丝 7190
获赞 186
Job

一个Job就是需要做的一个工作。通过实现Job接口来定义一个Job具体的业务逻辑。比如:

public class MyJob implements Job {

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Logger.getAnonymousLogger().info("MyJob");
    }
}
JobDetail和JobBuilder

上面介绍了一个Job的业务逻辑在哪里定义。那么如何把一个Job添加到我们的定时任务(调度)中呢?首先我们需要通过JobBuilder来构建一个JobDetail
代码大概是这个样子:

import static org.quartz.JobBuilder.*;
JobDetail job = newJob(MyJob.class)
  .withIdentity("myJob", "group1") // name "myJob", group "group1"
  .build();

需要注意的是这里的newJob方法是JobBuilder类的静态方法。这里使用了import static关键字。

另外需要注意的点是使用JobBuilder.newJob时需要传入Job接口的实现类的Class对象

JobDetail是一个接口, 它与Job不同的地方在于它可以获得一个Job更详细的信息。先来看看它有哪些方法:

public interface JobDetail extends Serializable, Cloneable {
    JobKey getKey();

    String getDescription();

    Class<? extends Job> getJobClass();

    JobDataMap getJobDataMap();

    boolean isDurable();

    boolean isPersistJobDataAfterExecution();

    boolean isConcurrentExectionDisallowed();

    boolean requestsRecovery();

    Object clone();

    JobBuilder getJobBuilder();
}

下面分别介绍几个重要的方法。

JobDataMap

首先我们看怎么用。

  // define the job and tie it to our DumbJob class
  JobDetail job = newJob(DumbJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .usingJobData("jobSays", "Hello World!")
      .usingJobData("myFloatValue", 3.141f)
      .build();

这里usingJobDataJobBuilder类的方法。在这里传入数据。这个方法有几个重载,第一个参数都是String类型的Key,第二个参数是一些基本类型的封装类型比如Integer等。查看源代码可以发现JobBuilder内部有一个JobDataMap类型的私有属性。而且所有的重载的usingJobData都是直接调用的这个私有属性的方法。代码如下:

private JobDataMap jobDataMap = new JobDataMap();

public JobBuilder usingJobData(String dataKey, String value) {
    this.jobDataMap.put(dataKey, value);
    return this;
}

public JobBuilder usingJobData(String dataKey, Integer value) {
    this.jobDataMap.put(dataKey, value);
    return this;
}

public JobBuilder usingJobData(String dataKey, Long value) {
    this.jobDataMap.put(dataKey, value);
    return this;
}

// ...

那么怎么取出这些值并使用呢?示例代码:

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);
    }
  }

可以看到在定义一个Job实现类的时候,从execute方法传入的JobExecutionContext对象获取到JobDetail,进一步获取到JobDataMap。再通过JobDataMap对象的getString等方法获取传入的值并使用。

查看JobDataMap可以发现它就是一个类似于Map的东西,不过封装了很多基本类型的包装类的方法,方便客户端使用。比如putAsString(String, int),对应的获取方法是getIntValue(String)。当然也有直接操作Object对象的get, put方法。

Job “实例”

你可以创建单个Job的实现类,然后在scheduler里面创建多个JobDetail实例。每个实例都有它自己的属性和JobDataMap

Quartz的术语中,我们通常称每个JobDetail为一个“Job定义”或者一个“JobDetail实例”,称每个可执行的Job也就是Job接口的实现类为一个“Job实例”或者一个“Job定义的实例”。通常我们说的Job指的是一个“JobDetail”。而当我们要说一个Job接口的实现类时,我们通常说”Job class“

Job状态和并发

从上面可以看到,JobDetail接口有以下两个方法:

boolean isPersistJobDataAfterExecution();

boolean isConcurrentExectionDisallowed();

这里有两个注解(写在Job接口的实现类上)分别对应这两个方法。

@DisallowConcurrentExecution

这个注解告诉Quartz,一个给定的Job定义(也就是一个JobDetail实例),不并发运行。

@PersistJobDataAfterExecution

意为:执行完后持久化JobData。这样当下次执行同样的JobDetail的时候,就会取得上一次执行后更新的数据。它也是作用与一个Job定义(也就是一个JobDetail实例)。

其它数据

同样是JobDetail接口里面的方法:

boolean isDurable();
boolean requestsRecovery();
Durability

一个Job是否是持久的标识。如果一个Job不是持久的,如果在scheduler里,没有了任何active状态的trigger跟它关联,那么就会被自动删除。

RequestsRecovery

如果一个Job是“RequestsRecovery”的,它执行过程中,scheduler被“中断”了,比如程序意外崩溃等。当scheduler重新开始后,这个Job也会重新执行。

参考文档

Quartz Tutorials 3: More About Jobs and Job Details


感谢您的阅读,若您喜欢,可以点击下方的的“推荐”支持我。谢谢!

也可以关注我的慕课账号,会经常更新Java、算法、Vue开发方面的文章哦~

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP