三、Quartz监听器

本文介绍了Quartz调度框架中的三种监听器——JobListener、TriggerListener和SchedulerListener,详细阐述了它们的功能、方法以及如何在任务调度过程中监听和响应不同事件。同时,提供了示例代码展示如何创建和注册全局与非全局监听器,以及它们在任务执行、触发器触发和调度器生命周期中的作用。
摘要由CSDN通过智能技术生成

1、概念

Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。Quartz监听器主要由JobListener、TriggerListener、SchedulerListener三种,顾名思义,分布表示任务、触发器、调度器对应的监听器。三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:

  • 全局监听器能够接收到所有的Job/Trigger的事件通知

  • 而非全局监听器只能接收到在其上注册的Job或者Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。

本课程关于全局与非全局的监听器的使用,将一一介绍。

2、JobListener

任务调度过程中,与任务Job相关的事件包括:Job开始要执行的提示;Job执行完成的提示等。

publicinterfaceJobListener {
    public String getName();
    publicvoidjobToBeExecuted(JobExecutionContext context);
    publicvoidjobExecutionVetoed(JobExecutionContext context);
    publicvoidjobWasExecuted(JobExecutionContext context, JobExecutionException jobException);
}
复制代码

其中:

. getName方法:用于获取该JobListener的名称。. jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法。. jobExecutionVetoed方法:Scheduler在JobDetail即将被执行,但又被TriggerListener否决时会调用该方法。. jobWasExecuted方法:Scheduler在JobDetail被执行之后调用这个方法。

示例:

HelloJobListener.java

// 定义任务类publicclassHelloJobListenerimplementsJob {

    @Overridepublicvoidexecute(JobExecutionContext context)throws JobExecutionException {
        // 输出当前时间Datedate=newDate();
        SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringdateString= dateFormat.format(date);
        // 工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:" +dateString);
    }
}
复制代码

创建自定义的JobListener

MyJobListener.java

publicclassMyJobListenerimplementsJobListener {

    @Overridepublic String getName() {
        Stringname=this.getClass().getSimpleName();
        System.out.println("监听器的名称是:" +name);
        return name;
    }

    @OverridepublicvoidjobToBeExecuted(JobExecutionContext context) {
        Stringname= context.getJobDetail().getKey().getName();
        System.out.println("Job的名称是:" +name + "          Scheduler在JobDetail将要被执行时调用的方法");
    }

    @OverridepublicvoidjobExecutionVetoed(JobExecutionContext context) {
        Stringname= context.getJobDetail().getKey().getName();
        System.out.println("Job的名称是:" +name + "          Scheduler在JobDetail即将被执行,但又被TriggerListener否决时会调用该方法");
    }

    @OverridepublicvoidjobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        Stringname= context.getJobDetail().getKey().getName();
        System.out.println("Job的名称是:" +name + "          Scheduler在JobDetail被执行之后调用这个方法");
    }

}
复制代码

执行调度器

HelloSchedulerDemoJobListener.java

publicclassHelloSchedulerDemoJobListener {

    publicstaticvoidmain(String[] args)throws Exception {
        // 1、调度器(Scheduler),从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)Schedulerscheduler= StdSchedulerFactory.getDefaultScheduler();

        // 2、任务实例(JobDetail)定义一个任务调度实例,将该实例与HelloJobSimpleTrigger绑定,任务类需要实现Job接口JobDetailjobDetail= JobBuilder.newJob(HelloJobListener.class) // 加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1") // 参数1:任务的名称(唯一实例);参数2:任务组的名称
                .build();

        // 3、触发器(Trigger)定义触发器,马上执行,然后每5秒重复执行一次Triggertrigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1") // 参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5).withRepeatCount(2))  // 每5秒执行一次,连续执行3次后停止,默认是0
                .build();
        // 4、让调度器关联任务和触发器,保证按照触发器定义的调整执行任务
        scheduler.scheduleJob(jobDetail, trigger);
        
        // 创建并注册一个全局的Job Listener// scheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs());// 创建并注册一个局部的Job Listener,表示指定的任务Job
        scheduler.getListenerManager().addJobListener(newMyJobListener(), KeyMatcher.keyEquals(JobKey.jobKey("job1", "group1")));

        // 5、启动
        scheduler.start();
        // 关闭//scheduler.shutdown();
    }

}
复制代码

3、TriggerListener

任务调度过程中,与触发器Trigger相关的事件包括:触发器触发、触发器未正确触发、触发器完成等。

publicinterfaceTriggerListener {
    public String getName();
    publicvoidtriggerFired(Trigger trigger, JobExecutionContext context);
    publicbooleanvetoJobExecution(Trigger trigger, JobExecutionContext context);
    publicvoidtriggerMisfired(Trigger trigger);
    publicvoidtriggerComplete(Trigger trigger, JobExecutionContext context,            CompletedExecutionInstruction triggerInstructionCode)
}
复制代码

其中:

. getName方法:用于获取触发器的名称。. triggerFired方法:当与监听器关联的Trigger被触发,Job上的Execute()方法将被执行时,Scheduler就调用该方法。. vetoJobExecution方法:在Trigger触发后,Job将要执行时由Scheduler调用这个方法。TriggerListener给了一个选择去否决Job的执行。假如这个方法返回true,这个Job将不会为此次Trigger触发而得到执行。. triggerMisfired方法:Scheduler调用这个方法是在Trigger错过触发时。你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的Trigger时,长逻辑会导致骨牌效应。你应当保持这个方法尽量的小。. triggerComplete方法:Trigger被触发并且完成了Job的执行时,Scheduler调用这个方法。

示例:

下面的例子简单展示了TriggerListener的使用,其中创建并注册TriggerListener与JobListener几乎类似。

HelloJobListener.java

// 定义任务类publicclassHelloJobListenerimplementsJob {

    @Overridepublicvoidexecute(JobExecutionContext context)throws JobExecutionException {
        // 输出当前时间Datedate=newDate();
        SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringdateString= dateFormat.format(date);
        // 工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:" +dateString);
    }
}
复制代码

MyTriggerListener.java

publicclassMyTriggerListenerimplementsTriggerListener {
    
    private String name;
    // 构造方法,自定义传递触发器的名称,默认是类的名称publicMyTriggerListener(String name) {
        super();
        this.name = name;
    }
    @Overridepublic String getName() {
        returnthis.name;  // 不返还会抛出一个名称为空的异常
    }

//    @Override//    public String getName() {//        String name = this.getClass().getSimpleName();//        System.out.println("触发器的名称:" +name);//        return name;  // 不返还会抛出一个名称为空的异常//    }@OverridepublicvoidtriggerFired(Trigger trigger, JobExecutionContext context) {
        Stringname=this.getClass().getSimpleName();
        System.out.println(name +"被触发");
    }

    @OverridepublicbooleanvetoJobExecution(Trigger trigger, JobExecutionContext context) {
        Stringname=this.getClass().getSimpleName();
        // TriggerListener给了一个选择去否决Job的执行。假如这个方法返回true,这个Job将不会为此次Trigger触发而得到执行。
        System.out.println(name +" 没有被触发");
        returnfalse;  // true:表示不会执行Job的方法
    }

    @OverridepublicvoidtriggerMisfired(Trigger trigger) {
        Stringname=this.getClass().getSimpleName();
        // Scheduler调用这个方法是在Trigger错过触发时
        System.out.println(name +" 错过触发");
    }

    @OverridepublicvoidtriggerComplete(Trigger trigger, JobExecutionContext context,
            CompletedExecutionInstruction triggerInstructionCode) {
        Stringname=this.getClass().getSimpleName();
        // Trigger被触发并且完成了Job的执行时,Scheduler调用这个方法。
        System.out.println(name +" 完成之后触发");
    }

}
复制代码

HelloSchedulerDemoTriggerListener.java

publicclassHelloSchedulerDemoTriggerListener {

    publicstaticvoidmain(String[] args)throws Exception {
        // 1、调度器(Scheduler),从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)Schedulerscheduler= StdSchedulerFactory.getDefaultScheduler();

        // 2、任务实例(JobDetail)定义一个任务调度实例,将该实例与HelloJobSimpleTrigger绑定,任务类需要实现Job接口JobDetailjobDetail= JobBuilder.newJob(HelloJobListener.class) // 加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1") // 参数1:任务的名称(唯一实例);参数2:任务组的名称
                .build();

        // 3、触发器(Trigger)定义触发器,马上执行,然后每5秒重复执行一次Triggertrigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1") // 参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5).withRepeatCount(2))  // 每5秒执行一次,连续执行3次后停止,默认是0
                .build();
        // 4、让调度器关联任务和触发器,保证按照触发器定义的调整执行任务
        scheduler.scheduleJob(jobDetail, trigger);

        // 创建并注册一个全局的Trigger Listener// scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(), EverythingMatcher.allTriggers());// 创建并注册一个局部的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(newMyTriggerListener(), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger1", "group1")));

        // 5、启动
        scheduler.start();
        // 关闭//scheduler.shutdown();
    }

}
复制代码

4、SchedulerListener

SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一个Job/Trigger,删除一个Job/Trigger,Scheduler发生严重错误,关闭Scheduler等。

publicinterfaceSchedulerListener {
    publicvoidjobScheduled(Trigger trigger);
    publicvoidjobUnscheduled(TriggerKey triggerKey);
    publicvoidtriggerFinalized(Trigger trigger);
    publicvoidtriggersPaused(String triggerGroup);
    publicvoidtriggersResumed(String triggerGroup);
    publicvoidjobsPaused(String jobGroup);
    publicvoidjobsResumed(String jobGroup);
    publicvoidschedulerError(String msg, SchedulerException cause);
    publicvoidschedulerStarted();
    publicvoidschedulerInStandbyMode();
    publicvoidschedulerShutdown();
    publicvoidschedulingDataCleared()
}
复制代码

其中:

. jobScheduled方法:用于部署JobDetail时调用。. jobUnscheduled方法:用于卸载JobDetail时调用。. triggerFinalized方法:当一个Trigger来到了再也不会触发的状态时调用这个方法。除非这个Job已设置成了持久性,否则它就会从Scheduler中移除。. triggersPaused方法:Scheduler调用这个方法是发生在一个Trigger或Trigger组被暂停时。假如是Trigger组的话,triggerName参数将为null。. triggersResumed方法:Scheduler调用这个方法是发生在一个Trigger或Trigger组从暂停中恢复时。假如是Trigger组的话,triggerName参数将为null。. jobsPaused方法:当一个或一组JobDetail暂停时调用这个方法。. jobsResumed方法:当一个或一组Job从暂停上恢复时调用这个方法。假如是一个Job组,jobName将为null。. schedulerError方法:在Scheduler的正常运行期间产生一个严重错误时调用这个方法。. schedulerStarted方法:当Scheduler开启时,调用该方法。. schedulerInStandbyMode方法:当Scheduler处于StandBy模式时,调用该方法。. schedulerShutdown方法:当Scheduler停止时,调用该方法。. schedulingDataCleared方法:当Scheduler中的数据被清除时,调用该方法。

示例:

下面的代码简单描述了如何使用SchedulerListener方法:

HelloJobListener.java

// 定义任务类publicclassHelloJobListenerimplementsJob {

    @Overridepublicvoidexecute(JobExecutionContext context)throws JobExecutionException {
        // 输出当前时间Datedate=newDate();
        SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringdateString= dateFormat.format(date);
        // 工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:" +dateString);
    }
}
复制代码

MySchedulerListener.java

publicclassMySchedulerListenerimplementsSchedulerListener {

    @OverridepublicvoidjobScheduled(Trigger trigger) {
        Stringname= trigger.getKey().getName();
        // 用于部署JobDetail时调用
        System.out.println(name +" 完成部署");
    }

    @OverridepublicvoidjobUnscheduled(TriggerKey triggerKey) {
        Stringname= triggerKey.getName();
        // 用于卸载JobDetail时调用
        System.out.println(name +" 完成卸载");
    }

    @OverridepublicvoidtriggerFinalized(Trigger trigger) {
        Stringname= trigger.getKey().getName();
        // 当一个Trigger来到了再也不会触发的状态时调用这个方法。除非这个Job已设置成了持久性,否则它就会从Scheduler中移除。
        System.out.println(name +" 触发器被移除");
    }

    @OverridepublicvoidtriggerPaused(TriggerKey triggerKey) {
        Stringname= triggerKey.getName();
        // Scheduler调用这个方法是发生在一个Trigger或Trigger组被暂停时。假如是Trigger组的话,triggerName参数将为null。
        System.out.println(name +" 正在被暂停");
    }

    @OverridepublicvoidtriggersPaused(String triggerGroup) {
        // Scheduler调用这个方法是发生在一个Trigger或Trigger组被暂停时。假如是Trigger组的话,triggerName参数将为null。
        System.out.println("触发器组" +triggerGroup +" 正在被暂停");
    }

    @OverridepublicvoidtriggerResumed(TriggerKey triggerKey) {
        // Scheduler调用这个方法是发生在一个Trigger或Trigger组从暂停中恢复时。假如是Trigger组的话,triggerName参数将为null。参数将为null。Stringname= triggerKey.getName();
        System.out.println(name +" 正在从暂停中恢复");
    }

    @OverridepublicvoidtriggersResumed(String triggerGroup) {
        // Scheduler调用这个方法是发生在一个Trigger或Trigger组从暂停中恢复时。假如是Trigger组的话,triggerName参数将为null。参数将为null。
        System.out.println("触发器组" +triggerGroup +" 正在从暂停中恢复");
    }

    @OverridepublicvoidjobAdded(JobDetail jobDetail) {
        // 
        System.out.println(jobDetail.getKey() +" 添加工作任务");
    }

    @OverridepublicvoidjobDeleted(JobKey jobKey) {
        // 
        System.out.println(jobKey +" 删除工作任务");
    }

    @OverridepublicvoidjobPaused(JobKey jobKey) {
        // 
        System.out.println(jobKey +" 工作任务正在被暂停");
    }

    @OverridepublicvoidjobsPaused(String jobGroup) {
        // 
        System.out.println("工作组" +jobGroup +" 正在被暂停");
    }

    @OverridepublicvoidjobResumed(JobKey jobKey) {
        // 
        System.out.println(jobKey +" 正在从暂停中恢复");
    }

    @OverridepublicvoidjobsResumed(String jobGroup) {
        // 
        System.out.println("工作组" +jobGroup +" 正在从暂停中恢复");
    }

    @OverridepublicvoidschedulerError(String msg, SchedulerException cause) {
        // 在Scheduler的正常运行期间产生一个严重错误时调用这个方法。
        System.out.println("产生严重错误的时候调用" +msg +"    " +cause.getUnderlyingException());
    }

    @OverridepublicvoidschedulerInStandbyMode() {
        // 当Scheduler处于StandBy模式时,调用该方法。
        System.out.println("调度器被挂起模式的时候调用");
    }

    @OverridepublicvoidschedulerStarted() {
        // 当Scheduler开启时,调用该方法
        System.out.println("调度器开启的时候调用");
    }

    @OverridepublicvoidschedulerStarting() {
        // 
        System.out.println("调度器正在开启的时候调用");
    }

    @OverridepublicvoidschedulerShutdown() {
        // 
        System.out.println("调度器关闭的时候调用");
    }

    @OverridepublicvoidschedulerShuttingdown() {
        // 
        System.out.println("调度器正在关闭的时候调用");
    }

    @OverridepublicvoidschedulingDataCleared() {
        // 当Scheduler中的数据被清除时,调用该方法
        System.out.println("调度器数据被清除的时候调用");
    }

}
复制代码

HelloSchedulerDemoTriggerListener.java

publicclassHelloSchedulerDemoTriggerListener {

    publicstaticvoidmain(String[] args)throws Exception {
        // 1、调度器(Scheduler),从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)Schedulerscheduler= StdSchedulerFactory.getDefaultScheduler();

        // 2、任务实例(JobDetail)定义一个任务调度实例,将该实例与HelloJobSimpleTrigger绑定,任务类需要实现Job接口JobDetailjobDetail= JobBuilder.newJob(HelloJobListener.class) // 加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1") // 参数1:任务的名称(唯一实例);参数2:任务组的名称
                .build();

        // 3、触发器(Trigger)定义触发器,马上执行,然后每5秒重复执行一次Triggertrigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1") // 参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5).withRepeatCount(2))  // 每5秒执行一次,连续执行3次后停止,默认是0
                .build();
        // 4、让调度器关联任务和触发器,保证按照触发器定义的调整执行任务
        scheduler.scheduleJob(jobDetail, trigger);

        // 创建调度器的监听
        scheduler.getListenerManager().addSchedulerListener(newMySchedulerListener());
        // 移除对应的调度器的监听// scheduler.getListenerManager().removeSchedulerListener(new MySchedulerListener());// 5、启动
        scheduler.start();

        // 线程延迟7秒后关闭
        Thread.sleep(7000L);

        // 关闭
        scheduler.shutdown();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Quartz是一个开源的作业调度框架,可以用来实现定时任务的调度和执行。它提供了很多的API和功能,其中一个重要的组件就是Trigger。Trigger是用来触发一个Job的执行的组件,可以理解为定时器。当Trigger满足一定的条件时,就会触发对应的Job执行。 Quartz中的Trigger有很多种类型,比如SimpleTrigger、CronTrigger等等,每种Trigger都有自己的特点和用途。在Quartz中,我们可以监听Trigger的状态变化,比如Trigger被触发、Trigger被暂停、Trigger被删除等等。通过监听Trigger的状态变化,我们可以在某些特定的时刻执行一些操作,比如记录日志、发送通知等等。 要监听Trigger的状态变化,我们需要实现Quartz提供的TriggerListener接口,该接口定义了一些回调方法,比如triggerFired、triggerPaused、triggerResumed等等。当Trigger的状态发生变化时,Quartz会自动调用对应的回调方法,我们可以在回调方法中执行相应的操作。 下面是一个简单的Trigger监听器的示例代码: ```java public class MyTriggerListener implements TriggerListener { public String getName() { return "MyTriggerListener"; } public void triggerFired(Trigger trigger, JobExecutionContext context) { System.out.println("Trigger fired: " + trigger.getKey()); } public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) { return false; } public void triggerMisfired(Trigger trigger) { System.out.println("Trigger misfired: " + trigger.getKey()); } public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) { System.out.println("Trigger completed: " + trigger.getKey()); } } ``` 在上面的代码中,我们实现了TriggerListener接口,并重写了其中的几个回调方法。getName方法返回该监听器的名称,triggerFired方法在Trigger被触发时被调用,triggerMisfired方法在Trigger错过触发时被调用,triggerComplete方法在Trigger完成后被调用。在每个回调方法中,我们可以实现自己的逻辑。最后,我们需要将该监听器注册到Quartz的Scheduler中: ```java scheduler.getListenerManager().addTriggerListener(new MyTriggerListener()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值