美文网首页
SpringBoot集成quartz注册全局监听器,项目重启后监

SpringBoot集成quartz注册全局监听器,项目重启后监

作者: 执念的鱼0118 | 来源:发表于2024-01-10 15:46 被阅读0次

    SpringBoot集成quartz的教程很多,这里不在赘述了。

    自定义监听器

    以下是自定义的监听器,继承了JobListenerSupport,主要就是做任务执行的日志记录。

    package com.zdww.szzf.investment.qrtz;
    
    import cn.hutool.extra.spring.SpringUtil;
    import com.zdww.szzf.investment.entity.SysJobsLog;
    import com.zdww.szzf.investment.service.ISysJobsLogService;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.quartz.listeners.JobListenerSupport;
    
    import java.time.Duration;
    import java.time.LocalDateTime;
    import java.util.Objects;
    
    /**
     * 任务监听
     *
     * @version 1.0
     * @date 2024/1/8 09:39
     **/
    @Slf4j
    public class ScheduleListener extends JobListenerSupport {
    
        private static final ThreadLocal<LocalDateTime> threadLocal = new ThreadLocal<>();
    
        /**
         * 任务执行成功
         */
        private static final String STATUS_SUCCESS = "1";
    
        /**
         * 任务执行失败
         */
        private static final String STATUS_FAIL = "0";
    
        @Override
        public String getName() {
            return "ScheduleListener";
        }
    
        @Override
        public void jobToBeExecuted(JobExecutionContext context) {
            LocalDateTime now = LocalDateTime.now();
            threadLocal.set(now);
            log.warn("任务执行开始,开始时间: {}", now);
        }
    
        @Override
        public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = threadLocal.get();
            long millis = Duration.between(start, end).toMillis();
            threadLocal.remove();
    
            SysJobsLog jobsLog = new SysJobsLog();
            jobsLog.setJobId(Long.valueOf(context.getJobDetail().getKey().getName()));
            jobsLog.setJobGroup(context.getJobDetail().getKey().getGroup());
            jobsLog.setJobName(context.getJobDetail().getDescription());
            jobsLog.setStartTime(start);
            jobsLog.setEndTime(end);
            if (Objects.nonNull(jobException)) {
                jobsLog.setStatus(STATUS_FAIL);
                jobsLog.setExceptionInfo(jobException.getMessage());
                log.warn("任务执行结束, 执行失败, 结束时间: {}", end);
            } else {
                jobsLog.setStatus(STATUS_SUCCESS);
                jobsLog.setJobMessage("执行成功, 耗时" + millis + "毫秒");
                log.warn("任务执行结束, 执行成功, 结束时间: {}", end);
            }
            SpringUtil.getBean(ISysJobsLogService.class).save(jobsLog);
        }
    
    }
    

    创建任务

    创建任务的时候注册一个全局的监听器

    public void addJob(SysJobs job) {
        try {
            Class<? extends Job> aClass = (Class<? extends Job>) Class.forName(JOB_PACKAGE + job.getInvokeTarget());
            JobDetail jobDetail = JobBuilder.newJob(aClass)
                    .withIdentity(String.valueOf(job.getId()), job.getJobGroup())
                    // 此处是把任务名称存放在Description,方便记录日志获取
                    .withDescription(job.getJobName())
                    .build();
    
            // 添加参数
            String extend = job.getExtend();
            if (StringUtils.isNotBlank(extend)) {
                jobDetail.getJobDataMap().putAll(JSON.parseObject(extend));
            }
    
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression())
                    // 过期任务丢弃
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(String.valueOf(job.getId()), job.getJobGroup())
                    .withDescription(job.getJobName())
                    .withSchedule(cronScheduleBuilder)
                    .build();
    
            JobKey jobKey = JobKey.jobKey(String.valueOf(job.getId()), job.getJobGroup());
    
            scheduler.getListenerManager().addJobListener(new ScheduleListener());
    
            // 如果已经存在则删除
            if (scheduler.checkExists(jobKey)) {
                scheduler.deleteJob(jobKey);
            }
    
            scheduler.scheduleJob(jobDetail, cronTrigger);
    
            // 状态是禁用的时候任务暂停
            if (StringUtils.equals(job.getStatus(), StatusEnum.DISABLED.getCode())) {
                scheduler.pauseJob(jobKey);
            }
        } catch (Exception e) {
            log.error("任务添加异常", e);
            throw new BusinessException("任务添加异常");
        }
    }
    

    问题:任务在执行的时候监听器正常执行,但是在项目重启后监听器不执行了...

    解决方案

    https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/tutorial-lesson-07.html

    在tutorial中看到了这一段描述恍然大悟

    Listeners are registered with the scheduler during run time, and are NOT stored in the JobStore along with the jobs and triggers. This is because listeners are typically an integration point with your application. Hence, each time your application runs, the listeners need to be re-registered with the scheduler.

    package com.zdww.szzf.investment.listener;
    
    import com.zdww.szzf.investment.qrtz.ScheduleListener;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobListener;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.context.event.ApplicationStartedEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
    
    /**
     * quartz 监听器注册
     * Listeners are registered with the scheduler during run time,
     * and are NOT stored in the JobStore along with the jobs and triggers.
     * This is because listeners are typically an integration point with your application.
     * Hence, each time your application runs, the listeners need to be re-registered with the scheduler.
     *
     * @version 1.0
     * @date 2024/1/11 14:33
     **/
    @Slf4j
    @Component
    public class JobListenerRegister implements ApplicationListener<ApplicationStartedEvent> {
    
        @Autowired
        private Scheduler scheduler;
    
        @Override
        public void onApplicationEvent(ApplicationStartedEvent event) {
            try {
                ScheduleListener scheduleListener = new ScheduleListener();
                scheduler.getListenerManager().addJobListener(scheduleListener);
                log.info("Scheduler 全局监听器注册成功");
            } catch (SchedulerException e) {
                log.error("Scheduler 全局监听器注册失败", e);
                throw new RuntimeException(e);
            }
        }
    }
    

    这样项目重新启动后监听器可以正常工作了。

    相关文章

      网友评论

          本文标题:SpringBoot集成quartz注册全局监听器,项目重启后监

          本文链接:https://www.haomeiwen.com/subject/pijzndtx.html