java jobdetail_Quartz 源码解析(三) —— JobDetail、Trigger和它们的Builder

大概内容

解析JobDetail

JobBuilder和Builder Pattern

类比解析Trigger

关于JobDetail

f466e02e2e94

JobDetail相关类

JobDetailImpl.java

JobDetailImpl是接口JobDetail的唯一实现类,本质上来说是一个Java Bean,这里主要是要理解各个属性的意思。

public class JobDetailImpl implements Cloneable, java.io.Serializable, JobDetail {

// Job的名称

private String name;

// Job的分组

private String group = Scheduler.DEFAULT_GROUP;

// Job的描述

private String description;

// 执行Job业务逻辑的对应实体类的Class引用

private Class extends Job> jobClass;

// 保存关于Job的信息,根据业务逻辑自己放进去

private JobDataMap jobDataMap;

// 当没有绑定Trigger的情况,是否保存Job

private boolean durability = false;

// Job是否可从“恢复”情况下再次执行

private boolean shouldRecover = false;

// 封装了name和group,作为JobDetail的唯一标识

// 用空间来换取时间和可读性的策略

private transient JobKey key = null;

}

JobKey

JobKey没有特殊的代码逻辑,都是借助于父类Key的能力。

public final class JobKey extends Key {

public JobKey(String name) {

super(name, null);

}

public JobKey(String name, String group) {

super(name, group);

}

// 其他代码

}

public class Key implements Serializable, Comparable> {

/**

* The default group for scheduling entities, with the value "DEFAULT".

*/

public static final String DEFAULT_GROUP = "DEFAULT";

private final String name;

private final String group;

/**

* name不允许为空,group没有指定值则自动赋值为"DEFAULT"

*/

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;

}

// 其他代码

/**

* 先比较group,再比较name

*/

public int compareTo(Key o) {

if(group.equals(DEFAULT_GROUP) && !o.group.equals(DEFAULT_GROUP))

return -1;

if(!group.equals(DEFAULT_GROUP) && o.group.equals(DEFAULT_GROUP))

return 1;

int r = group.compareTo(o.getGroup());

if(r != 0)

return r;

return name.compareTo(o.getName());

}

/**

* 如果name为空,那么在JobBuilder或者TriggerBuilder的build()方法会调用此方法根据group自动生成一个name。

*/

public static String createUniqueName(String group) {

if(group == null)

group = DEFAULT_GROUP;

String n1 = UUID.randomUUID().toString();

String n2 = UUID.nameUUIDFromBytes(group.getBytes()).toString();

return String.format("%s-%s", n2.substring(24), n1);

}

}

JobDataMap

JobDataMap提供了一个Map的对象,我们可以在管理或者执行Job的过程中保存或者查询一些自定义的信息。

在第一篇的案例里面,是通过JobBuilder的usingJobData()方法放进去一些信息。

public class JobDataMap extends StringKeyDirtyFlagMap implements Serializable {

public JobDataMap() {

super(15);

}

public JobDataMap(Map, ?> map) {

this();

@SuppressWarnings("unchecked") // casting to keep API compatible and avoid compiler errors/warnings.

Map mapTyped = (Map)map;

putAll(mapTyped);

// When constructing a new data map from another existing map, we should NOT mark dirty flag as true

// Use case: loading JobDataMap from DB

clearDirtyFlag();

}

/**

* 提供很多个重载不同数据类型的putAsString()方法,都是父类对StringKeyDirtyFlagMap的简单封装

*/

public void putAsString(String key, boolean value) {

String strValue = Boolean.valueOf(value).toString();

super.put(key, strValue);

}

// 其他代码

/**

* 提供很多个不同数据类型的getXXX()方法,都是父类对StringKeyDirtyFlagMap的简单封装

*/

public boolean getBooleanValueFromString(String key) {

Object obj = get(key);

return Boolean.valueOf((String) obj);

}

public boolean getBooleanValue(String key) {

Object obj = get(key);

if(obj instanceof String) {

return getBooleanValueFromString(key);

} else {

return getBoolean(key);

}

}

// 其他代码

}

关于JobBuilder

Builder Pattern

封装一个产品的构造过程,并允许按步骤构造,并且可以改变过程(这和只有一个步骤的工厂模式不同)。与工厂模式相比,采用Builder Pattern来创建对象的Client,需要具备更多的领域知识。

JobBuilder

将JobDetail的属性都封装起来

允许JobDeatil通过多个步骤来创建,并且可以改变过程或者顺序

// 3.创建JobDetail

JobDetail jobDetail = JobBuilder.newJob(RAMJob.class)

.withDescription("this is a ram job") //job的描述

.withIdentity("ramJob", "ramGroup") //job 的name和group

.build();

JobBuilder的属性和JobDetail的属性基本一致,这样得以在build()方法里面,完成对JobDetail进行创建。

// JobBuilder.java

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;

}

JobBilder的大部分方法都是返回自身的引用,这样得以多个步骤的方式来完善JobDetail的属性内容。

JobBuilder.withIdentity()主要是设置属性值。

JobBuilder.usingJobData()主要是设置JobDataMap字段。

public class JobBuilder {

public JobBuilder withIdentity(String name)

public JobBuilder withIdentity(String name, String group)

public JobBuilder withIdentity(JobKey jobKey)

public JobBuilder withDescription(String jobDescription)

public JobBuilder ofType(Class extends Job> jobClazz)

public JobBuilder requestRecovery()

public JobBuilder requestRecovery(boolean jobShouldRecover)

public JobBuilder storeDurably()

public JobBuilder storeDurably(boolean jobDurability)

public JobBuilder usingJobData(String dataKey, String value)

public JobBuilder usingJobData(String dataKey, Integer value)

public JobBuilder usingJobData(String dataKey, Long value)

public JobBuilder usingJobData(String dataKey, Float value)

public JobBuilder usingJobData(String dataKey, Double value)

public JobBuilder usingJobData(String dataKey, Boolean value)

public JobBuilder usingJobData(JobDataMap newJobDataMap)

public JobBuilder setJobData(JobDataMap newJobDataMap)

}

类比解析Trigger

相关类的类图

f466e02e2e94

Trigger相关类

TriggerBuilder

TriggerBuilder是一个泛型类,与JobBuilder有点不一样,而且创建Trigger实例的动作委托给了ScheduleBuilder类。ScheduleBuilder,这次不顾名思义了,它作为一个生成器,不是要生成Scheduler类,而是要生成MutableTrigger实例。

在第一篇的案例里面,ScheduleBuilder使用的具体对象是CronScheduleBuilder。

// 4.创建Trigger

Trigger trigger = TriggerBuilder.newTrigger().withDescription("")

.withIdentity("ramTrigger", "ramTriggerGroup")

.startAt(new Date()) // 默认当前时间启动

.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) // 两秒执行一次

.usingJobData("triggerKey", "some important information to save")

.build();

TriggerBuilder.java

public class TriggerBuilder {

private TriggerKey key;

private String description;

private Date startTime = new Date();

private Date endTime;

private int priority = Trigger.DEFAULT_PRIORITY;

private String calendarName;

private JobKey jobKey;

private JobDataMap jobDataMap = new JobDataMap();

private ScheduleBuilder> scheduleBuilder = null;

private TriggerBuilder() {

}

public T build() {

if(scheduleBuilder == null)

scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();

MutableTrigger trig = scheduleBuilder.build();

trig.setCalendarName(calendarName);

trig.setDescription(description);

trig.setStartTime(startTime);

trig.setEndTime(endTime);

if(key == null)

key = new TriggerKey(Key.createUniqueName(null), null);

trig.setKey(key);

if(jobKey != null)

trig.setJobKey(jobKey);

trig.setPriority(priority);

if(!jobDataMap.isEmpty())

trig.setJobDataMap(jobDataMap);

return (T) trig;

}

// 其他代码

}

CronScheduleBuilder.java

public class CronScheduleBuilder extends ScheduleBuilder {

private CronExpression cronExpression;

private int misfireInstruction = CronTrigger.MISFIRE_INSTRUCTION_SMART_POLICY;

protected CronScheduleBuilder(CronExpression cronExpression) {

if (cronExpression == null) {

throw new NullPointerException("cronExpression cannot be null");

}

this.cronExpression = cronExpression;

}

/**

* Build the actual Trigger -- NOT intended to be invoked by end users, but

* will rather be invoked by a TriggerBuilder which this ScheduleBuilder is

* given to.

*

* @see TriggerBuilder#withSchedule(ScheduleBuilder)

*/

@Override

public MutableTrigger build() {

CronTriggerImpl ct = new CronTriggerImpl();

ct.setCronExpression(cronExpression);

ct.setTimeZone(cronExpression.getTimeZone());

ct.setMisfireInstruction(misfireInstruction);

return ct;

}

// 其他代码

}

系列文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值