上一篇文章我记录了自己封装的QuartzUtil工具类,同时写了一个quartz骨架项目,以便大家理解使用。可在公众号quartz专栏查看。
正文开始
quartz源码分析第一部分:记录创建定时任务相关的源码。由于不想篇幅太长,所以这一部分将依次分成三篇文章:(这是三篇中的第一篇)
创建JobDetail(JobBuilder详解)
创建CronTrigger(TriggerBuilder详解)
关联JobDetail和Trigger(Scheduler详解)
一、创建定时任务
这是QuartzUtil中创建定时任务的方法。之后的部分将通过这个方法浅析quartz在创建Job时是怎么一步步实现的。
/** * * 在创建任务时未设置jobGroup和triggerGroup,Job创建后其均为默认值:DEFAULT, * 因此新创建的任务的jobName和triggerName,均不能与之前任务的重复. * * @param jobName 任务名 * @param triggerName 触发器名 * @param description 对该任务的秒数(非必须) * @param jobClass 要执行的任务 * @param cron cron表达式 * @return true:创建Job成功,false:创建Job失败 */public static boolean addJob(String jobName, String triggerName, String description, Class<T> jobClass, String cron) { try { JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(jobName) .withDescription(description)// .usingJobData("param1", "将参数")// .usingJobData("param2", "传递到JOB任务中使用") .build(); CronTrigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity(triggerName) .startNow() .withSchedule(CronScheduleBuilder.cronSchedule(cron)) .build(); scheduler.scheduleJob(jobDetail, cronTrigger); if (!scheduler.isShutdown()) { scheduler.start(); } return scheduler.isStarted(); } catch (Exception e) { throw new CustomException(Code.EXECUTION_ERROR); }}
二、创建JobDetail(JobBuilder详解)
首先介绍一下JobBuilder,他是用来实例化一个定时任务的。在quartz中这个定时任务就是JobDetail。当然JobDetail是一个接口,真正的实现类是JobDetailImpl,而在这个JobDetailImpl中保存的就是定时任务的相关信息。
(1) JobBuilder.newJob()
/** * 创建用于定义JobDetail的JobBuilder,并设置需要定时执行的任务类。 * * @param jobClass 需要定时执行的任务类,该类需要实现Job接口 * @return a new JobBuilder */public static JobBuilder newJob(Class extends Job> jobClass) { JobBuilder b = new JobBuilder(); b.ofType(jobClass); //设置将要执行的Job return b;}
(2) JobBuilder.ofType()
/** * 设置在触发与此JobDetail关联的触发器时,将实例化并执行的类。 * * @param jobClazz a class implementing the Job interface. * @return the updated JobBuilder */public JobBuilder ofType(Class extends Job> jobClazz) { this.jobClass = jobClazz; return this;}
(3) JobBuilder.withIdentity()
/** * 使用给定的任务名称和默认的任务组名来创建JobKey,JobKey是定时任务JobDetail的标志。 * 如果在JobBuilder上没有设置任何“withIdentity”方法,则将生成一个随机的、惟一的JobKey。 * * @param name 定时任务名称 * @return the updated JobBuilder */public JobBuilder withIdentity(String name) { key = new JobKey(name, null); return this;}
withIdentity还有两个重载的方法,如下所示:
public JobBuilder withIdentity(String name, String group) { key = new JobKey(name, group); return this;}public JobBuilder withIdentity(JobKey jobKey) { this.key = jobKey; return this;}
现在就一清二楚,withIdentity()方法的作用就是生成JobKey,赋值给JobBuilder的属性key。
接下来看一下,JobKey是如何生成的。
(4) JobKey
JobKey继承自Key,他提供两个构造方法,作用均为调用父类的构造方法,另外两个静态方法也是类似的作用。
JobKey是JobDetail的唯一标识,他由任务名称(name)和任务组名称(group)组成,并且name在group中必须是惟一的。如果只指定了name,那么将使用默认的组名称(DEFAULT)来创建JobKey。
public final class JobKey extends Key<JobKey> { private static final long serialVersionUID = -6073883950062574010L; public JobKey(String name) { super(name, null); } public JobKey(String name, String group) { super(name, group); } public static JobKey jobKey(String name) { return new JobKey(name, null); } public static JobKey jobKey(String name, String group) { return new JobKey(name, group); }}
(5) Key
Key是quartz中用于标识JobDetail和Trigger的对象。他有两个子类,一个是JobKey,另一个是TriggerKey,分别是JobDetail和Trigger的唯一标识。TriggerKey与JobKey基本没有区别,在下一篇文章中将会讲到TriggerKey的相关代码。
public class Key<T> implements Serializable, Comparable<Key<T>> { private static final long serialVersionUID = -7141167957642391350L; //任务组默认名称 public static final String DEFAULT_GROUP = "DEFAULT"; //任务名 private final String name; //任务组名 private final String group; /** * name等于null时,抛出IllegalArgumentException。 * name、group不为null时,使用给定的name和group创建Key。 * group等于null时,使用name和默认任务组名'DEFAULT'创建Key。 * * @param name 任务名称 * @param group 任务组名称 */ public Key(String name, String group) { if(name == null) throw new IllegalArgumentException("Name cannot be null."); this.name = name; if(group != null) this.group = group; else this.group = DEFAULT_GROUP; } public String getName() { return name; } public String getGroup() { return group; } //...省略类中其他方法:toString()、hashCode()、equals()、compareTo()、createUniqueName()}
(6) JobBuilder.withDescription()
这个方法很简单就是用来给这个定时任务增加一个描述的。具体如下:
/** * 给任务设置一个有意义的描述 * * @param jobDescription 对任务的描述 * @return the updated JobBuilder */public JobBuilder withDescription(String jobDescription) { this.description = jobDescription; return this;}
(7) JobBuilder.usingJobData()
这个方法的作用是我们可以通过键值对的方式将一些参数传到定时任务中,在定时任务中使用。
/** * 将给定的键-值对添加到JobDetail的JobDataMap * * @return the updated JobBuilder * @see JobDetail#getJobDataMap() */public JobBuilder usingJobData(String dataKey, String value) { jobDataMap.put(dataKey, value); return this;}
(8) JobBuilder.build()
该方法就是实例化一个JobDetailImpl,然后将JobBuilder中的参数设置的JobDetailImpl中返回。
/** * 生成此JobBuilder定义的JobDetail实例 * * @return the defined JobDetail. */public JobDetail build() { JobDetailImpl job = new JobDetailImpl(); job.setJobClass(jobClass); job.setDescription(description); if(key == null) key = new JobKey(Key.createUniqueName(null), null); job.setKey(key); job.setDurability(durability); job.setRequestsRecovery(shouldRecover); if(!jobDataMap.isEmpty()) job.setJobDataMap(jobDataMap); return job;}
三、总结
(1) JobDetail
JobDetail是用来表达给定Job的详细属性信息的,作者的原话是:"Conveys the detail properties of a given Job instance.",
JobDetail是一个接口,只有一个实现类JobDetailImpl,这是真正保存Job详细属性的类。在JobDetailImpl中主要有以下参数:
参数 | 类型 | 默认值 | 说明 |
name | String | 无 | 任务名称 |
group | String | "DEFAULT" | 任务组名称 |
description | String | 无 | 任务描述 |
jobClass | Class extends Job> | 无 | 真正需要执行的Job任务类 |
jobDataMap | JobDataMap | 无 | 实现了Map接口,用于保存需要传递给Job的参数信息 |
durability | boolean | false | 当没有trigger与Job关联时,是否需要保存Job |
shouldRecover | boolean | false | 如果遇到“恢复”或“故障转移”情况,Scheduler是否应重新执行Job |
key | JobKey | 无 | JobDetail的唯一标识,他由任务名称(name)和任务组名称(group)组成 |
(2) JobBuilder
JobBuilder采用build模式,用于实例化一个JobDetail。JobBuilder的属性与JobDetail一模一样(除了没有name和group),当我们使用JobBuild的其他方法时都是将Job详细信息先保存到JobBuilder中,最后调用build方法时,new一个JobDetailImpl,然后将保存的参数都设置到JobDetailImpl中,然后返回。
四、关注回复【book】获取资源
关注获取更多资源