Springboot整合Quartz任务框架

  分享一篇关于Springboot整合Quartz任务框架在实际开发中的使用,基于SpringBoot2.0+Mybatis+Oracle开发
1. 导入jar包

<!-- 定时任务 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- 其他的jar包请自行添加 -->

2. 配置任务调度器

@Configuration
public class ScheduleConfig {
    /**
     * 解决Job中注入Spring Bean为null的问题
     */
    @Component("quartzJobFactory")
    public static class QuartzJobFactory extends AdaptableJobFactory {
        private final AutowireCapableBeanFactory capableBeanFactory;
        public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
            this.capableBeanFactory = capableBeanFactory;
        }
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            //调用父类的方法
            Object jobInstance = super.createJobInstance(bundle);
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }

    /**
     * 注入scheduler到spring
     */
    @Bean(name = "scheduler")
    public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setJobFactory(quartzJobFactory);
        factoryBean.afterPropertiesSet();
        Scheduler scheduler = factoryBean.getScheduler();
        scheduler.start();
        return scheduler;
    }
}

3. 配置定时任务执行的方法

@Slf4j
@Component
public class ScheduleJob extends QuartzJobBean {
    @Autowired
    private SysQuartzLogService logService;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        SysQuartzLogEntity logs = new SysQuartzLogEntity();
        // 执行时传入的任务信息
        SysQuartzJobEntity job = (SysQuartzJobEntity) context.getMergedJobDataMap().get("JOB_PARAM_KEY");
        // TODO 任务日志记录
        logs.setBeanName(job.getBeanName());
        logs.setCreateTime(new Date());
        logs.setCronExpression(job.getCronExpression());
        logs.setJobName(job.getJobName());
        logs.setMethodName(job.getMethodName());
        logs.setParams(job.getParams());
        // 开始时间
        Long startTime = System.currentTimeMillis();
        try {
        	// 通过反射的方式去执行方法
            // 获取需要执行的类实例
            Object target = SpringContextUtils.getBean(job.getBeanName());
            if (target != null) {
                // 获取需要执行的方法
                if (StringUtils.hasText(job.getParams())) {
                    Method method = target.getClass().getDeclaredMethod(job.getMethodName(), String.class);
                    // 执行方法
                    method.invoke(target, job.getParams());
                } else {
                    Method method = target.getClass().getDeclaredMethod(job.getMethodName());
                    // 执行方法
                    method.invoke(target);
                }
                logs.setIsSuccess(0);
            }
            // 执行时长
            Long time = System.currentTimeMillis() - startTime;
            logs.setTime(String.valueOf(time));
        } catch (Exception e) {
            log.error("定时任务执行失败:{}", e);
            logs.setIsSuccess(1);
            logs.setExceptionDetail(e.getMessage());
            Long time = System.currentTimeMillis() - startTime;
            logs.setTime(String.valueOf(time));
            // TODO 出现异常可以通过邮件进行通知
        } finally {
        	// 保存任务执行的日志
            logService.saveLog(logs);
        }

    }
}

4. 配置定时任务工具类

public class ScheduleUtils {
    /**
     * 任务名前缀
     */
    public final static String JOB_NAME = "TASK_";
    /**
     * 分组名前缀
     */
    public final static String JOB_GROUP = "GROUP_";

    /**
     * 获取触发器KEY
     */
    public static TriggerKey getTriggerKey(String jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId, JOB_GROUP + jobId);
    }

    /**
     * 获取job key
     */
    public static JobKey getJobKey(String jobId) {
        return JobKey.jobKey(JOB_NAME + jobId, JOB_GROUP + jobId);
    }

    /**
     * 获取cron表达式的触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, String jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
        }
    }

    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            // 构建JOB信息
            JobDetail detail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build();
            // Cron表达式调度器
            CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            // 按照新的cron创建新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId())).withSchedule(builder).build();
            //放入参数,运行时的方法可以获取
            detail.getJobDataMap().put(Constant.JOB_PARAM_KEY, job);
            // 执行任务
            scheduler.scheduleJob(detail, trigger);
            // 暂停任务
            if (job.getIsPause().equals(1)) {
                pauseJob(scheduler, job);
            }
        } catch (Exception e) {
            throw new RuntimeException("创建定时任务失败:{}", e);
        }
    }

    /**
     * 更新定时任务
     */
    public static void updateScheduleJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            isHasJob(scheduler, job);
            TriggerKey triggerKey = getTriggerKey(job.getJobId());
            //表达式调度构建器
            CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = getCronTrigger(scheduler, job.getJobId());
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(builder).build();
            //放入参数,运行时的方法可以获取
            trigger.getJobDataMap().put(Constant.JOB_PARAM_KEY, job);
            scheduler.rescheduleJob(triggerKey, trigger);
            //暂停任务(系统启动时调用此方法,需要判断任务的状态)
            if (job.getIsPause().equals(1)) {
                pauseJob(scheduler, job);
            }
        } catch (Exception e) {
            throw new RuntimeException("更新定时任务失败", e);
        }
    }

    /**
     * 立即执行任务
     */
    public static void run(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            isHasJob(scheduler, job);
            //放入参数,运行时的方法可以获取
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(Constant.JOB_PARAM_KEY, job);
            scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
        } catch (Exception e) {
            throw new RuntimeException("定时任务执行失败", e);
        }
    }

    /**
     * 暂停任务
     */
    public static void pauseJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            isHasJob(scheduler, job);
            scheduler.pauseJob(getJobKey(job.getJobId()));
        } catch (Exception e) {
            throw new RuntimeException("定时任务暂停失败", e);
        }
    }

    /**
     * 恢复定时任务
     */
    public static void resumeJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            isHasJob(scheduler, job);
            scheduler.resumeJob(getJobKey(job.getJobId()));
        } catch (Exception e) {
            throw new RuntimeException("恢复定时任务失败", e);
        }
    }

    /**
     * 删除定时任务
     */
    public static void deleteScheduleJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            scheduler.deleteJob(getJobKey(job.getJobId()));
        } catch (Exception e) {
            throw new RuntimeException("删除定时任务失败", e);
        }
    }

    /**
     * 判断是否存在任务
     * 不存在则创建一个
     */
    private static void isHasJob(Scheduler scheduler, SysQuartzJobEntity job) {
        try {
            CronTrigger cronTrigger = getCronTrigger(scheduler, job.getJobId());
            if (cronTrigger == null) {
                createScheduleJob(scheduler, job);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 配置spring context 工具类

public class SpringContextUtils implements ApplicationContextAware {
    public static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtils.applicationContext = applicationContext;
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }
}

sql

CREATE TABLE TS_SYS_QUARTZ_LOG
(
    "LOG_ID"           VARCHAR2(25)         NOT NULL,
    "BEAN_NAME"        VARCHAR2(250)        NOT NULL,
    "CREATE_TIME"      DATE DEFAULT sysdate NOT NULL,
    "CRON_EXPRESSION"  VARCHAR2(250)        NOT NULL,
    "EXCEPTION_DETAIL" VARCHAR2(250),
    "IS_SUCCESS"       NUMBER               NOT NULL,
    "JOB_NAME"         VARCHAR2(250)        NOT NULL,
    "METHOD_NAME"      VARCHAR2(250)        NOT NULL,
    "PARAMS"           VARCHAR2(250),
    "TIME"             VARCHAR2(250)        NOT NULL
);
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.LOG_ID IS '日志id';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.BEAN_NAME IS 'bean名称';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.CREATE_TIME IS '创建时间';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.CRON_EXPRESSION IS 'cron表达式';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.EXCEPTION_DETAIL IS '异常信息';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.IS_SUCCESS IS '是否成功,0-成功,1-失败';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.JOB_NAME IS 'JOB名称';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.METHOD_NAME IS '方法名';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.PARAMS IS '参数';
COMMENT ON COLUMN TS_SYS_QUARTZ_LOG.TIME IS '时间';

CREATE TABLE TS_SYS_QUARTZ_JOB
(
    "JOB_ID"              VARCHAR2(15)              NOT NULL,
    "BEAN_NAME"           VARCHAR2(250)             NOT NULL,
    "CRON_EXPRESSION"     VARCHAR2(250)             NOT NULL,
    "IS_PAUSE"            NUMBER(1) DEFAULT 0       NOT NULL,
    "JOB_NAME"            VARCHAR2(250)             NOT NULL,
    "METHOD_NAME"         VARCHAR2(250)             NOT NULL,
    "PARAMS"              VARCHAR2(250),
    "DESCRIPTION"         VARCHAR2(250)             NOT NULL,
    "PERSON_IN_CHARGE"    VARCHAR2(250)             NOT NULL,
    "EMAIL"               VARCHAR2(250),
    "SUB_TASK"            VARCHAR2(250)             NOT NULL,
    "PAUSE_AFTER_FAILURE" NUMBER(2)                 NOT NULL,
    "CREATE_BY"           VARCHAR2(250)             NOT NULL,
    "UPDATE_BY"           VARCHAR2(250),
    "CREATE_TIME"         DATE      DEFAULT sysdate NOT NULL,
    "UPDATE_TIME"         DATE
);
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.JOB_ID IS 'ID';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.BEAN_NAME IS 'Spring Bean名称';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.CRON_EXPRESSION IS 'cron 表达式';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.IS_PAUSE IS '状态,0-执行,1-暂停,2-删除';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.JOB_NAME IS '任务名称';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.METHOD_NAME IS '方法名称';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.PARAMS IS '参数';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.DESCRIPTION IS '备注';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.PERSON_IN_CHARGE IS '负责人';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.EMAIL IS '报警邮箱';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.SUB_TASK IS '子任务ID';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.PAUSE_AFTER_FAILURE IS '任务失败后是否暂停';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.CREATE_BY IS '创建者';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.UPDATE_BY IS '更新者';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.CREATE_TIME IS '创建日期';
COMMENT ON COLUMN TS_SYS_QUARTZ_JOB.UPDATE_TIME IS '更新时间';
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

華小灼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值