天天看點

定時任務排程架構Quartz--JobListeners

文章目錄

  • ​​基礎監聽接口JobListener​​
  • ​​配置全局監聽器​​
  • ​​配置局部監聽器​​
  • ​​KeyMatcher​​
  • ​​GroupMatcher​​
  • ​​OrMatcher​​
  • ​​EverythingMatcher​​

基礎監聽接口JobListener

        JobListener接口方法及其源碼

方法名 作用
getName 此監聽器對象的名稱
jobToBeExecuted 在監聽的JobDetail執行個體即将執行之前觸發
jobExecutionVetoed Scheduler 在 JobDetail 即将被執行,但又被 TriggerListener 否決了時觸發這個方法
jobWasExecuted 在監聽的JobDetail執行個體執行完成後觸發
public interface JobListener {
    public String getName();
    public void jobToBeExecuted(JobExecutionContext context);
    public void jobExecutionVetoed(JobExecutionContext context);
    public void jobWasExecuted(JobExecutionContext context,
            JobExecutionException jobException);
}      

        成為一個JobDetail隻需要實作JobListener接口即可。下面是我的自定義實作。

public class MyJobListener implements JobListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyJobListener.class);

    @Override
    public String getName() {
        return "myJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        JobDetail jobDetail = context.getJobDetail();
        //觸發前做日志等記錄
        LOGGER.error(getName() + "觸發對JobDetail[" + jobDetail.hashCode() 
                                + "]執行之前的監聽,做預處理");
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        //該JobDetail執行個體被Trigger否決觸發
        JobDetail jobDetail = context.getJobDetail();
        LOGGER.error(getName() + "觸發對" + jobDetail.hashCode() + "的Trigger否決監聽任務");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        JobDetail jobDetail = context.getJobDetail();
        try {
            //觸發後做日志等記錄,執行時間分析
            LOGGER.error(getName() + "觸發對JobDetail[" + jobDetail.hashCode() 
                                                                + "]執行完成之後的監聽,做後處理");
            LOGGER.error("排程器名稱:" + context.getScheduler().getSchedulerName());
            LOGGER.error("任務名稱:" + jobDetail.getKey().getName());
            LOGGER.error("任務分組:" + jobDetail.getKey().getGroup());
            LOGGER.error("觸發器TriggerID:" + context.getFireInstanceId());
            LOGGER.error("本次觸發完成時間:" + 
                    DateTransformTools.dateToDateStr(context.getFireTime()));
            LOGGER.error("下次觸發執行時間:" + 
                    DateTransformTools.dateToDateStr(context.getNextFireTime()));

        } catch (Exception e) {
            LOGGER.error(getName() + "觸發對JobDetail[" + jobDetail.hashCode()
                                                                + "]後處理出現異常");
        }
    }
}      

        當然了,也可以擴充JobListenerSupport類,并且隻需覆寫你感興趣的事件

配置全局監聽器

        配置全局監聽,隻需要把JobListener接口實作配置到Scheduler中。

scheduler.getListenerManager().addJobListener(jobListenerImpl);      

        下面是我的測試用例

public static void main(String[] args) {
        try {
            //define the job and bind it to our HelloJob class
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();

            JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").
                    build();

            Trigger trigger = newTrigger().withIdentity("trigger2", "group1")
                    .usingJobData("格言3", "奧特曼豬豬俠閃電小子葫蘆娃")
                    .startAt(DateBuilder.todayAt(10, 0, 0))
                    .withSchedule(cronSchedule("0 0/1 11 * * ?").
                            //錯過的任務全部忽略
                            withMisfireHandlingInstructionDoNothing())
                    .forJob("job1", "group1").build();

            //添加全局Job監聽
            MyJobListener myJobListener = new MyJobListener();
            scheduler.getListenerManager().addJobListener(myJobListener);
            
            //用我們的觸發告訴schedule安排工作
            scheduler.scheduleJob(job,trigger);

            //在調用shutdown()之前,你需要給job的觸發和執行預留一些時間,比如,你可以調用
            Thread.sleep(1000000000);
            scheduler.shutdown();
        } catch (Exception e) {
            LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
        }
    }


    public static class HelloJob implements Job {

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            LOGGER.error("現在是:{},JobInstanceId:{}", 
                       DateTransformTools.dateToDateStr(new Date()), this.hashCode());
        }
    }
}      
定時任務排程架構Quartz--JobListeners

​上述程式目的在10點鐘開始執行,每一分鐘執行一次定時任務。從實際效果上來看,監聽器監聽到JobDetail執行個體的執行。說明自定義的JobListener配置成全局Job監聽器成功。​

配置局部監聽器

#全局Job監聽配置核心代碼
scheduler.getListenerManager().addJobListener(jobListenerImpl);      
KeyMatcher

       為單個Job配置監聽器,使用JobKey進行比對。

scheduler.getListenerManager().addJobListener(myJobListener, 
                         KeyMatcher.keyEquals(JobKey.jobKey("job1", "group1")));
                         
//或者直接把JobDetail傳進來,這樣寫
scheduler.getListenerManager().addJobListener(myJobListener, 
                         KeyMatcher.keyEquals(jobDetail.getKey()));      
GroupMatcher

       使用Group進行比對。下面是對整個叫做“group1”的Job組增加監聽器

.getListenerManager().addJobListener(myJobListener, 
                                        GroupMatcher.jobGroupEquals("group1"));      
OrMatcher
.getListenerManager().addJobListener(myJobListener,
                    OrMatcher.or(
                            GroupMatcher.jobGroupEquals("group1"), 
                            GroupMatcher.jobGroupEquals("group2"))
                       );      
EverythingMatcher
scheduler.getListenerManager().addJobListener(myJobListener,EverythingMatcher.allJobs());