一个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();
这里usingJobData
是JobBuilder
类的方法。在这里传入数据。这个方法有几个重载,第一个参数都是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的实现类,然后在scheduler里面创建多个JobDetail
实例。每个实例都有它自己的属性和JobDataMap
。
在Quartz的术语中,我们通常称每个JobDetail
为一个“Job定义”或者一个“JobDetail实例”,称每个可执行的Job也就是Job
接口的实现类为一个“Job实例”或者一个“Job定义的实例”。通常我们说的Job指的是一个“JobDetail”。而当我们要说一个Job
接口的实现类时,我们通常说”Job class“
从上面可以看到,JobDetail
接口有以下两个方法:
boolean isPersistJobDataAfterExecution();
boolean isConcurrentExectionDisallowed();
这里有两个注解(写在Job
接口的实现类上)分别对应这两个方法。
这个注解告诉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开发方面的文章哦~
共同学习,写下你的评论
评论加载中...
作者其他优质文章