初识Quartz之Trigger组件

        前文已经介绍了Job组件,本文介绍Trigger组件,其实Trigger组件关系网与Job组件关系网类似。

1.trigger接口

        首先Trigger是个接口,继承了Serializable、Cloneable、Comparable接口。

public interface Trigger extends Serializable, Cloneable, Comparable<Trigger>

        可以看出该Trigger接口与JobDetail接口的不同之处在于继承了Comparable接口,并且在Trigger接口内部有一个内部类TriggerTimeComparator类,该类的主要目的是为了给触发器进行排序,

class TriggerTimeComparator implements Comparator<Trigger>, Serializable {
      
        private static final long serialVersionUID = -3904243490805975570L;
        
        // This static method exists for comparator in TC clustered quartz
        public static int compare(Date nextFireTime1, int priority1, TriggerKey key1, Date nextFireTime2, int priority2, TriggerKey key2) {
            if (nextFireTime1 != null || nextFireTime2 != null) {
                if (nextFireTime1 == null) {
                    return 1;
                }

                if (nextFireTime2 == null) {
                    return -1;
                }

                if(nextFireTime1.before(nextFireTime2)) {
                    return -1;
                }

                if(nextFireTime1.after(nextFireTime2)) {
                    return 1;
                }
            }

            int comp = priority2 - priority1;
            if (comp != 0) {
                return comp;
            }

            return key1.compareTo(key2);
        }

        以上这个类是一个比较器,用于比较触发器的下一次触发时间,或者换言之,根据最早的下一次触发时间对它们进行排序。 如果触发时间相同,则根据优先级(最高值优先)对触发器进行排序,如果优先级相同,则按键排序。所以这是在使用多个触发器的时候用于触发器执行先后的比较器。

2.TriggerBuilder类

        由于Trigger是个接口,因此Trigger的对象创建不能直接使用Trigger接口创建实例,因此通过调用TriggerBuilder类进行创建实例,首先调用TriggerBuilder的类方法,该方法封装了TriggerBuilder对象的创建过程。

 public static TriggerBuilder<Trigger> newTrigger() {
        return new TriggerBuilder<Trigger>();
    }

        然后调用TriggerBuilder实例方法withIdentity方法,并为触发器命名与分组。该方法封装了创建TriggerKey对象的过程。

public TriggerBuilder<T> withIdentity(String name) {
        key = new TriggerKey(name, null);
        return this;
    }  
    
    /**
     * Use a TriggerKey with the given name and group to
     * identify the Trigger.
     * 
     * <p>If none of the 'withIdentity' methods are set on the TriggerBuilder,
     * then a random, unique TriggerKey will be generated.</p>
     * 
     * @param name the name element for the Trigger's TriggerKey
     * @param group the group element for the Trigger's TriggerKey
     * @return the updated TriggerBuilder
     * @see TriggerKey
     * @see Trigger#getKey()
     */
    public TriggerBuilder<T> withIdentity(String name, String group) {
        key = new TriggerKey(name, group);
        return this;
    }
    
    /**
     * Use the given TriggerKey to identify the Trigger.  
     * 
     * <p>If none of the 'withIdentity' methods are set on the TriggerBuilder,
     * then a random, unique TriggerKey will be generated.</p>
     * 
     * @param triggerKey the TriggerKey for the Trigger to be built
     * @return the updated TriggerBuilder
     * @see TriggerKey
     * @see Trigger#getKey()
     */
    public TriggerBuilder<T> withIdentity(TriggerKey triggerKey) {
        this.key = triggerKey;
        return this;
    }

        TriggerKey继承了Key,构造函数继承了父类构造函数。

public final class TriggerKey extends Key<TriggerKey> {
  
    private static final long serialVersionUID = 8070357886703449660L;

    public TriggerKey(String name) {
        super(name, null);
    }

    public TriggerKey(String name, String group) {
        super(name, group);
    }

    public static TriggerKey triggerKey(String name) {
        return new TriggerKey(name, null);
    }
    
    public static TriggerKey triggerKey(String name, String group) {
        return new TriggerKey(name, group);
    }
    
}

        以下是Key的构造函数的源码,其中name是必须的,而group是可以为null,如果为null,默认值为DEFAULT_GROUP,这也解释了TriggerBuilder类中有重载的withIdentity方法,其中就有group参数缺省的,但是没有name参数缺省的。

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

        因此从上面可以知道,调用TriggerBuilder的withIdentity方法就可以并可以绑定触发器的名字与分组两个参数,并且返回的是TriggerBuilder对象。

3.触发器的启动设置

        以上创建了TriggerBuilder对象,因此在创建Trigger对象过程中还需要做启动相关的设置,比如何时启动,何时结束,以及触发频率等设置。

        首先是何时启动的设置,TriggerBuilder中提供了两个实例方法,startAt(Date startTime)和startNow(),前者根据传入的具体时间进行确定启动时间,而后者则是即刻启动。

 public TriggerBuilder<T> startAt(Date triggerStartTime) {
        this.startTime = triggerStartTime;
        return this;
    }
    
    /**
     * Set the time the Trigger should start at to the current moment - 
     * the trigger may or may not fire at this time - depending upon the 
     * schedule configured for the Trigger.  
     * 
     * @return the updated TriggerBuilder
     * @see Trigger#getStartTime()
     */
    public TriggerBuilder<T> startNow() {
        this.startTime = new Date();
        return this;
    }

        至于何时结束,TriggerBuilder提供了一个endAt(Date triggerEndTime)方法,该方法主要确定了该触发器终止时间。

public TriggerBuilder<T> endAt(Date triggerEndTime) {
        this.endTime = triggerEndTime;
        return this;
    }

        TriggerBuilder提供了withSchedule(ScheduleBuilder<SBT> schedBuilder)方法用于设置触发频率等设置。

public <SBT extends T> TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> schedBuilder) {
        this.scheduleBuilder = schedBuilder;
        return (TriggerBuilder<SBT>) this;
    }

        可以看出withSchedule的方法中传入的是ScheduleBuilder对象,以下是ScheduleBuilder抽象类。有一个抽象方法build。

public abstract class ScheduleBuilder<T extends Trigger>  {
    
    protected abstract MutableTrigger build();

}

    ScheduleBuilder有两个类叫做SimpleScheduleBuilder和CronScheduleBuilder,这其实表示两种调度器。以SimpleScheduleBuilder为例,该类有一个类方法用于封装创建ScheduleBuilder对象,该方法如下:

 public static SimpleScheduleBuilder simpleSchedule() {
        return new SimpleScheduleBuilder();
    }
    

    其中SimpleScheduleBuilder有许多实例方法,用于触发频率的控制。比如:withIntervalInSeconds(int intervalInSeconds)、withIntervalInMinutes(int intervalInMinutes)等等,用于调度器的相关参数的设置。其中有一个

        根据以上方法将ScheduleBuilder对象传入以及调度器相关配置传入Trigger对象的withSchedule方法完成对Trigger对象有关调度器的配置。最后调用Trigger对象的build()方法,该方法返回的是Trigger对象,从而实现Trigger对象的创建。

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

        以上方法表示,如果ScheduleBuilder对象为空,先对其进行初始化对象,然后创建一个Trigger对象,该对象是MutableTrigger类型的,通过ScheduleBuilder对象的Build()方法实现创建Trigger对象,然后对其进行绑定一些Trigger相关的信息。以下是ScheduleBuilder对象的实例方法build,该方法返回的是MutableTrigger类型对象,用于创建Trigger对象。

public MutableTrigger build() {

        SimpleTriggerImpl st = new SimpleTriggerImpl();
        st.setRepeatInterval(interval);
        st.setRepeatCount(repeatCount);
        st.setMisfireInstruction(misfireInstruction);
        
        return st;
    }
        根据以上分析可以看出获取Trigger对象,需要通过TriggerBuilder类调用相应的类方法创建TriggerBuilder对象,然后通过TriggerBuilder对象的实例方法绑定信息,启动设置,以及调度设置,最后调用实例方法build进行封装Trigger对象的创建过程从而实现创建Trigger对象。
QuartzTrigger 类是调度任务执行时间的关键组件之一。在 Quartz 中,`org.quartz.NthIncludedDayTrigger` 特别用于指定每隔特定天数运行某个作业(Job)的触发器。这个类允许你在特定的周期内选择某一天作为作业的执行日。 下面是一个简单的示例,展示了如何创建一个 `NthIncludedDayTrigger`: ```java // 引入所需的包 import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.text.SimpleDateFormat; import java.util.Date; // 定义具体的间隔(比如每周一) int nthDay = 1; // 第一天 String dayOfWeek = "Monday"; // 周一 // 创建日期格式化对象 SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy"); // 获取当前日期 Date currentDate = new Date(); String currentDateString = sdf.format(currentDate); // 计算下一次满足条件的日期 Date nextExecutionDate = getNthDayAfter(currentDate, nthDay, dayOfWeek); // 创建 NthIncludedDayTrigger NthIncludedDayTrigger trigger = new NthIncludedDayTrigger(); trigger.setRepeatCount(Trigger.REPEAT_INDEFINITELY); // 设置无限循环 trigger.setStartAt(nextExecutionDate); // 设置首次执行时间 trigger.setNextFireTime(nextExecutionDate); trigger.setIntervalInMilliseconds(1000 * 60 * 60 * 24); // 每周一次,单位毫秒 trigger.setNthWeekday(nthDay); // 设置为周一 trigger.setFirstDayOfWeek(DayOfWeek.MONDAY); // 配合 nthDay 使用 // 启动 Quartz 安排器并设置触发器 StdSchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.start(); // 添加触发器到调度器 scheduler.scheduleJob(trigger, new JobDetail()); ``` 在这个示例中,我们首先计算出下次满足条件的日期(即下周一),然后创建一个 `NthIncludedDayTrigger` 并设置其属性。最后,我们将触发器添加到 Quartz 调度器中以安排任务执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值