StdScheduler 触发器配置定时任务

本文介绍了一个基于SpringBoot实现的定时任务系统,包括任务配置、任务执行和任务管理等核心功能。通过具体代码示例展示了如何创建和管理定时任务。
package com.sanyi.collect.service.job;

import com.sanyi.entity.SyTask;
import com.sanyi.collect.entity.vo.RunTaskVO;
import com.sanyi.collect.entity.vo.SyTaskVO;
import com.sanyi.collect.enums.EnableStatusEnum;
import com.sanyi.collect.enums.RunTaskTypeEnum;
import com.sanyi.enums.TaskActionEnum;
import com.sanyi.collect.service.SyTaskService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author ceshi
 * @Description 作业基类
 * @date 2021/6/2510:40
 */
@Component
@Slf4j
public class BaseBizJob {

    /**
     * id标识
     */
    private static final long BEAT_JOB_ID = 1L;
    /**
     * 默认用户名
     */
    private static final String TASK_USER = "System";
    @Autowired
    BizManageJob bizManageJob;
    @Autowired
    SyTaskService syTaskService;

    /**
     * 运行
     *
     * @param jobExecutionContext
     * @return void
     * @throws
     * @author sunwy
     * @date 2021/11/2
     */
    protected void run(JobExecutionContext jobExecutionContext) {

        try {
            JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
            Object obj = jobDataMap.get("taskId");
            SyTaskVO syTaskVO = (SyTaskVO) obj;
            //传递参数是否为空
            if (syTaskVO == null) {
                log.info("JobDataMap is null");
                return;
            }
            //是否心跳任务
            log.info("{} start at:{}", syTaskVO.getTaskName(), new Date());
            if (syTaskVO.getId() == BEAT_JOB_ID) {
                log.info("beat job ...");
                return;
            }
            //业务逻辑
            SyTask task = syTaskService.getById(syTaskVO.getId());
            if (task == null) {
                log.info("该任务已删除:{}", syTaskVO.getTaskName());
                return;
            }
            //任务状态是否禁用
            if (task.getStatus() != null && task.getStatus().equals(EnableStatusEnum.DISABLE.getValue())) {
                bizManageJob.deleteJob(task);
                return;
            }
            //截止时间为空则永久运行
            if (task.getEndTime() != null) {
                if (task.getEndTime().getTime() - System.currentTimeMillis() < 0) {
                    bizManageJob.deleteJob(task);
                    return;
                }
            }
            //执行任务
            syTaskService.runTask(RunTaskVO.builder().taskType(RunTaskTypeEnum.INCR)
                    .action(TaskActionEnum.AUTO)
                    .operator(TASK_USER).id(syTaskVO.getId()).build());

            log.info("{} end at:{}", syTaskVO.getTaskName(), new Date());
        } catch (Exception e) {
            log.error("BaseBizJob run error ", e);
        }
    }
}

1.首先配置定时作业基类

/**
 * @author ceshi
 * @Title:
 * @Package
 * @Description: 表资产同步作业
 * @date 2021/6/2316:28
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class TableSyncJob extends BaseBizJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        super.run(jobExecutionContext);
    }
}

2.定时任务类

package com.sanyi.collect.config;

import com.sanyi.entity.SyTask;
import com.sanyi.collect.enums.EnableStatusEnum;
import com.sanyi.collect.service.SyTaskService;
import com.sanyi.collect.service.job.BeatJob;
import com.sanyi.collect.service.job.BizManageJob;
import com.sanyi.collect.service.job.ClusterBeatLogJob;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author ceshi
 * @Title:
 * @Package
 * @Description: springboot 启动后执行方法
 * @date 2021/6/2319:17
 */
@Component
@Order(value = 1)
public class ApplicationStartQuartzJob implements ApplicationRunner {

    @Resource
    SyTaskService syTaskService;
    @Resource
    BizManageJob bizManageJob;
    private static final long BEAT_JOB_ID = 1L;
    /**
     * 每隔十分钟检查一次
     */
    private static final String BEAT_CRON_EXPRESSION = "0 0/10 * * * ?";
    /**
     * 任务组名称
     */
    private static final String TASK_GROUP = "SANY";
    /**
     * 异常任务状态检查名称
     */
    private static final String TASK_NAME = "异常任务状态检查";

    /**
     * 1、查询数据库配置任务
     * 2、循环添加任务到触发器
     * 3、界面提供修改任务执行的cron表达式(停止任务可以修改其他参数)
     * 4、启动和停止任务调用添加任务和移除任务方法
     *
     * @param args
     * @return void
     * @author sunwy
     * @date 2021/7/10
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        if (syTaskService != null && bizManageJob != null) {
            List<SyTask> taskList = syTaskService.findAll();
            //添加作业
            bizManageJob.addJob(SyTask.builder().className(BeatJob.class.getName())
                    .id(BEAT_JOB_ID)
                    .cronExpression(BEAT_CRON_EXPRESSION)
                    .startTime(new Date())
                    .endTime(null)
                    .taskName(TASK_NAME)
                    .status(EnableStatusEnum.ENABLE.getValue())
                    .taskGroup(TASK_GROUP).build());
            //添加作业
            bizManageJob.addJob(SyTask.builder().className(ClusterBeatLogJob.class.getName())
                    .id(-1L)
                    .cronExpression("0 */1 * * * ?")
                    .startTime(new Date())
                    .endTime(null)
                    .taskName("task-cluster-check")
                    .status(EnableStatusEnum.ENABLE.getValue())
                    .taskGroup(TASK_GROUP).build());
            taskList.forEach(task -> bizManageJob.addJob(task));
        }
    }
}

3.启动后就加载的方法添加定时任务

/**
     * 添加定时任务
     *
     * @param task
     */
    @SuppressWarnings("unchecked")
    public void addJob(SyTask task) {
        log.info("新增定时任务:{}", task.getTaskName());
        JobDetail jobDetail;
        if (StringUtils.isEmpty(task.getClassName())) {
            log.error("定时任务 {} className为空,无法启动", task.getTaskName());
            return;
        }
        if (StringUtils.isEmpty(task.getCronExpression())) {
            log.error("定时任务 {} CronExpression为空,无法启动", task.getTaskName());
            return;
        }
        Class<?> aClass;
        try {
            aClass = Class.forName(task.getClassName());
        } catch (ClassNotFoundException e) {
            log.error("{} 未找到执行作业类,无法启动", task.getClassName());
            return;
        }
        SyTaskVO taskVO = SyTaskVO.builder()
                .className(task.getClassName())
                .cronExpression(task.getCronExpression())
                .endTime(task.getEndTime())
                .id(task.getId())
                .field(task.getIncrField())
                .from(task.getIncrFrom())
                .startTime(task.getStartTime())
                .taskName(task.getTaskName())
                .status(task.getStatus())
                .taskGroup(task.getTaskGroup())
                .build();

        CronTrigger trigger = null;
        // 调度容器设置JobDetail和Trigger
        try {
            //初始化触发器key
            TriggerKey triggerKey = TriggerKey.triggerKey(String.valueOf(task.getId()), task.getTaskGroup());
            //判断是否已经存在,存在则启动,不存在则创建新的触发器
            boolean flag = scheduler.checkExists(triggerKey);
            if (flag) {
                //触发器已存在,则停止触发器
                scheduler.pauseTrigger(triggerKey);
                //卸载触发器
                scheduler.unscheduleJob(triggerKey);
                //移除作业
                scheduler.deleteJob(JobKey.jobKey(String.valueOf(task.getId()), task.getTaskGroup()));
            }
            //传递参数
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("taskId", taskVO);
            String taskName = task.getId().toString();
            //初始化作业信息
            jobDetail = JobBuilder.newJob((Class<? extends Job>) aClass).withIdentity(taskName, task.getTaskGroup())
                    .usingJobData(jobDataMap).build();
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            //现在开始
            triggerBuilder.startNow();
            // 创建Trigger对象
            trigger = TriggerBuilder.newTrigger().withIdentity(String.valueOf(task.getId()), task.getTaskGroup()).withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).build();
            //加入调度器
            scheduler.scheduleJob(jobDetail, trigger);
            //开始调度
            scheduler.start();
        } catch (SchedulerException e) {
            log.error("添加定时任务失败", e);
        }
        log.info("新增定时任务结束:{}", task.getTaskName());
    }

4.添加定时任务到  Scheduler调度器中

package com.sanyi.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;

import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 * 任务属性表
 * </p>
 *
 * @author sunwy
 * @since 2021-06-21
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SyTask implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;

    /**
     * 任务名称
     */
    private String taskName;
    /**
     * 任务组
     */
    private String taskGroup;

    /**
     * cron表达式
     */
    private String cronExpression;
    /**
     * 增量字段
     */
    private String incrField;

    /**
     * 增量字段开始
     */
    private Date incrFrom;

    /**
     * 启动作业时间
     */
    private Date startTime;

    /**
     * 作业截止时间
     */
    @TableField(value = "end_time", updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.DATE)
    private Date endTime;

    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    /**
     * 创建人
     */
    private String createBy;

    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /**
     * 修改人
     */
    private String updateBy;


    private Integer status;

    private String className;

    /**
     * 是否展示
     */
    private Integer isShow;

    /**
     * 是否显示增量执行按钮
     */
    @TableField("is_show_incr")
    private Integer isShowIncr;
    /**
     * 是否显示全量执行按钮
     */
    @TableField("is_show_all")
    private Integer isShowAll;
}

4.1 存储在数据库的定时任务配置信息bean类

@Override
    public void runTask(RunTaskVO taskVO) {
        log.info("dmap task run {}", taskVO.getId());
        SyTaskQueue syTaskQueue = addTaskQueue(taskVO);
        try {
            syTaskQueueService.add(syTaskQueue);
            //api作业
            runApiJob(taskVO, syTaskQueue);
            //表资产采集作业
            runTableJob(taskVO, syTaskQueue);
            //报表采集作业
            //runReportJob(taskVO, syTaskQueue);
            //血缘关系作业
            runCapitalRelationshipJob(taskVO, syTaskQueue);
            //api目录作业
            runApiCategoryJob(taskVO, syTaskQueue);
            //资产热度作业
            runCapitalOperationHeatJob(syTaskQueue);
            //api到kafka作业
            runApiToKafkaJob(taskVO, syTaskQueue);
            //数据产品到kafka作业
            //runDataToKafkaJob(taskVO, syTaskQueue);
            //新指标血缘同步任务作业
            runIndicatorToKafkaJob(taskVO, syTaskQueue);
            //新指标到kafka作业
             runSyMetricsToKafkaJob(taskVO, syTaskQueue);
            //数据表到kafka作业
            runTableToKafkaJob(taskVO, syTaskQueue);
            //报表到kafka作业
            //runReportToKafkaJob(taskVO, syTaskQueue);
            //资产脱敏规则采集作业
            runSensitiveDataJob(taskVO, syTaskQueue);
            //指标落地表字段更新作业
            runIndicatorFieldUpdateJob(taskVO, syTaskQueue);
            //老指标同步kafka
            runIndicatorSourceUpdateJob(syTaskQueue);
            //指标落地表详细信息作业
            runIndicatorFieldInfoUpdateJob(syTaskQueue);
            //资产pv定时清理作业
            runCapitalDeletedHistoryPVJob(syTaskQueue);
            //hbase同步码表作业
            runHbaseToSyMapJob(taskVO, syTaskQueue);
            //更新任务完成状态 完成时间
            syTaskQueue.setTaskStatus(TaskQueueStatusEnum.FINISHED.getValue());
            syTaskQueue.setTaskEnd(new Date());
            syTaskQueueService.updateById(syTaskQueue);
        } catch (Exception e) {
            log.info("runTask ", e);
            syTaskQueue.setTaskStatus(TaskQueueStatusEnum.FAILURE.getValue());
            syTaskQueue.setTaskEnd(new Date());
            syTaskQueue.setReason(e.getMessage());
            syTaskQueueService.updateById(syTaskQueue);
        }

    }

5.根据定时id执行特定定时任务

/**
 * @author ceshi
 * @Title:
 * @Package
 * @Description: 表资产同步作业
 * @date 2021/6/2316:28
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class TableSyncJob extends BaseBizJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        super.run(jobExecutionContext);
    }
}

6.执行某一个定时任务

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值