定时任务框架quartz+spring boot实战

quartz官方文档:http://www.quartz-scheduler.org/documentation/

Quartz 是一个功能丰富的开源任务调度库,可以集成到任何 Java 应用程序中——从最小的独立应用程序到最大的电子商务系统。Quartz 可用于创建简单或复杂的计划,以执行数十、数百甚至数万个作业; 这些作业的任务被定义为标准的 Java 组件,可以编程让它们执行任何任务。Quartz Scheduler 包含许多企业级特性,例如对 JTA 事务和集群的支持。

集成spring boot步骤:

添加依赖

<!--定时任务-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

添加配置

添加的配置项包括持久化任务,配置任务的线程,任务随应用启动等。

spring:
    quartz:
        properties:
          org:
            quartz:
              scheduler:
                #调度程序名称
                instanceName: workScheduler
                instanceId: AUTO
              jobStore:
                #无需将调度事务绑定到其它事务,使用JobStoreTX
                class: org.quartz.impl.jdbcjobstore.JobStoreTX
                #跟数据库初始化脚本中配置保持一致
                driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
                #Quartz 表的前缀
                tablePrefix: QRTZ_
                #设置为“true”以打开集群特性。如果 Quartz 的多个实例使用同一组数据库表,那么这个属性必须设置为“ true”
                isClustered: true
                #与集群其它实例检查的频率(ms)
                clusterCheckinInterval: 10000
                #为true则JobDataMaps中类型都为string,不用存BLOB
                useProperties: false
              threadPool:
                class: org.quartz.simpl.SimpleThreadPool
                #可用于并发执行作业的线程数
                threadCount: 20
                #线程优先级
                threadPriority: 5
                threadsInheritContextClassLoaderOfInitializingThread: true
        job-store-type: jdbc
        #覆盖已有任务
        overwrite-existing-jobs: true
        #自动启动
        auto-startup: true

添加持久化任务数据表

需要这些数据表来持久化任务
运行tables_mysql_innodb.sql创建Job Stores所需的数据表,sql文件在软件包中

数据表用途:
qrtz_blob_triggers : 以Blob 类型存储的触发器。
qrtz_calendars:存放日历信息, quartz可配置一个日历来指定一个时间范围。
qrtz_cron_triggers:存放cron类型的触发器。
qrtz_fired_triggers:存放已触发的触发器。
qrtz_job_details:存放一个JobDetail信息。
qrtz_job_listeners:job监听器。
qrtz_locks: 存储程序的悲观锁的信息(假如使用了悲观锁)。
qrtz_paused_trigger_graps:存放暂停掉的触发器。
qrtz_scheduler_state:调度器状态。
qrtz_simple_triggers:简单触发器的信息。
qrtz_trigger_listeners:触发器监听器。
qrtz_triggers:触发器的基本信息。

cron方式需要用到的4张数据表:
qrtz_triggers,qrtz_cron_triggers,qrtz_fired_triggers,qrtz_job_details

创建任务监听器

可以监听任务调度前后和任务被拒绝

package com.training.examination.work.quartz;

import org.jboss.logging.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

public class SchedulerListener implements JobListener {
    public static final String LISTENER_NAME = "QuartSchedulerListener";

    private static final Logger logger = Logger.getLogger(SchedulerListener.class);

    @Override
    public String getName() {
        return LISTENER_NAME;
    }

    /**
     * 任务被调度前
     *
     * @param context
     */
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        String jobName = context.getJobDetail().getKey().toString();
        logger.info("Job: " + jobName + " 开始执行");
    }

    /**
     * 任务调度被拒绝
     *
     * @param context
     */
    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        String jobName = context.getJobDetail().getKey().toString();
        logger.info("Job: " + jobName + " 被拒绝");
    }

    /**
     * 任务被调度后
     *
     * @param context
     * @param jobException
     */
    @Override
    public void jobWasExecuted(JobExecutionContext context,
                               JobExecutionException jobException) {
        String jobName = context.getJobDetail().getKey().toString();
        logger.info("Job: " + jobName + " 执行结束");

        if (jobException != null && !"".equals(jobException.getMessage())) {
            logger.error("Exception thrown by: " + jobName
                    + " Exception: " + jobException.getMessage());
        }
    }
}

创建任务调度器

调度包括任务的启动、停止、暂停、恢复

package com.training.examination.work.quartz;

import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SchedulerManager {

    private final Scheduler scheduler;
    private JobListener scheduleListener;

    /**
     * 开始定时任务
     *
     * @param jobName
     * @param jobGroup
     * @throws SchedulerException
     */
    public void startJob(String cron, String jobName, String jobGroup, Class<? extends Job> jobClass, String parameter) throws SchedulerException {
        if (scheduleListener == null) {
            scheduleListener = new SchedulerListener();
            scheduler.getListenerManager().addJobListener(scheduleListener);
        }
        JobKey jobKey = new JobKey(jobName, jobGroup);
        if (!scheduler.checkExists(jobKey)) {
            /*
             *  此处可以先通过任务名查询数据库,如果数据库中存在该任务,更新任务的配置以及触发器
             *  如果此时数据库中没有查询到该任务,则按照下面的步骤新建一个任务,并配置初始化的参数,并将配置存到数据库中
             */
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            Map map = (Map) JSON.parse(parameter);
            for (Object object : map.keySet()) {
                jobDataMap.put(object.toString(), map.get(object).toString());
            }
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(
                    jobName, jobGroup).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, cronTrigger);
        }
    }

    /**
     * 移除定时任务
     *
     * @param jobName
     * @param jobGroup
     * @throws SchedulerException
     */
    public void deleteJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.deleteJob(jobKey);
    }

    /**
     * 暂停定时任务
     *
     * @param jobName
     * @param jobGroup
     * @throws SchedulerException
     */
    public void pauseJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复定时任务
     *
     * @param jobName
     * @param jobGroup
     * @throws SchedulerException
     */
    public void resumeJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey triggerKey = new JobKey(jobName, jobGroup);
        scheduler.resumeJob(triggerKey);
    }

    /**
     * 清空所有当前scheduler对象下的定时任务【目前只有全局一个scheduler对象】
     *
     * @throws SchedulerException
     */
    public void clearAll() throws SchedulerException {
        scheduler.clear();
    }

}

创建任务执行类

也就是任务本身

package com.training.examination.work.quartz.jobs;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.training.examination.core.common.Constant;
import com.training.examination.core.util.DateUtil;
import com.training.examination.work.entity.ExamManageConfig;
import com.training.examination.work.entity.ExamRecord;
import com.training.examination.work.entity.MonthTrainingPlan;
import com.training.examination.work.service.IExamManageConfigService;
import com.training.examination.work.service.IExamService;
import com.training.examination.work.service.IMonthTrainingPlanService;
import com.training.examination.work.service.INoticeService;
import com.training.examination.work.vo.ExamRecordVO;
import org.jboss.logging.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class NoticeJob implements Job {

	//这里注入需要的service
    @Autowired
    private IExamManageConfigService examManageConfigService;

    private static final Logger logger = Logger.getLogger(NoticeJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
		//获取任务参数
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        long param1 = jobDataMap.getLongValue("param1");
		//执行任务逻辑...
		
    }
}

Cron表达式

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

Seconds Minutes Hours DayOfMonth Month DayOfWeek Year

Seconds Minutes Hours DayOfMonth Month DayOfWeek

每一个域可出现的字符如下:
Seconds:可出现", - * /“四个字符,有效范围为0-59的整数
Minutes:可出现”, - * /“四个字符,有效范围为0-59的整数
Hours:可出现”, - * /“四个字符,有效范围为0-23的整数
DayOfMonth:可出现”, - * / ? L W C"八个字符,有效范围为0-31的整数
Month:可出现", - * /“四个字符,有效范围为1-12的整数或JAN-DEc
DayOfWeek:可出现”, - * / ? L C #“四个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year:可出现”, - * /"四个字符,有效范围为1970-2099年

如项目中每天早上8点运行任务,则表达式为

0 0 8 1/1 * ? *

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值