SpringBoot整合持久化功能的Quartz

单体应用,任务持久化到数据库,省略了数据库交互的代码

package com.yang.springbootquartz.rest;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * @author: Yang
 * @date: 2018/8/9 22:54
 * @description: 前台的调度任务持久化到数据库
 * 每个任务需要有唯一key,避免重复任务
 */
@Slf4j
@RestController
@RequestMapping("/my")
public class MyQuartzController {

    @Resource
    private Scheduler scheduler;

    /**
     * 添加调度任务
     */
    @PostMapping("/add")
    private void add(@RequestBody Task task) throws Exception {
        //1.查询数据库,避免重复复
        //2.任务入库
        //3.删除任务,防止重复
        this.deleteFromQuartz(task.getJobClassName());
        //4.将任务托管给quartz
        this.addToQuartz(task.getJobClassName(), task.getCronExpression(), task.getParam());
        //5.将数据库中对应记录的状态修改为已托管
    }

    /**
     * 将任务托管到Quartz框架
     *
     * @param className
     * @param cronExpression
     * @param param
     */
    void addToQuartz(String className, String cronExpression, String param) throws Exception {
        //0.利用Quartz内置方法,校验cron表达式的合法性,前端可用此正则【/^[a-zA-Z]+(\.([a-zA-Z])+)+$/】进行校验
        if (!CronExpression.isValidExpression(cronExpression)) {
            log.error("cron表达式不合法");
            return;
        }

        // 1.构建job信息
        JobDetail jobDetail = JobBuilder
                .newJob(getClass(className).getClass())
                .withIdentity(className)
                .usingJobData("param", param)
                .build();

        // 2.表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        // 3.按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(className).withSchedule(scheduleBuilder).build();

        // 4.装载job和trigger
        this.scheduler.scheduleJob(jobDetail, trigger);

        // 5.启动调度器
        this.scheduler.start();
    }

    /**
     * 删除调度任务
     *
     * @param task
     * @throws SchedulerException
     */
    @PostMapping("/delete")
    public void delete(@RequestBody Task task) throws SchedulerException {
        //1.删除已托管到quartz中的任务
        this.deleteFromQuartz(task.getJobClassName());
        //2.删除数据库记录
    }

    /**
     * @param className
     */
    void deleteFromQuartz(String className) throws SchedulerException {
        //1.暂停任务的trigger
        this.scheduler.pauseTrigger(TriggerKey.triggerKey(className));

        //2.取消任务的调度
        this.scheduler.unscheduleJob(TriggerKey.triggerKey(className));

        //3.删除任务
        this.scheduler.deleteJob(JobKey.jobKey(className));
    }

    private static Job getClass(String className) throws Exception {
        Class<?> class1 = Class.forName(className);
        return (Job) class1.newInstance();
    }

}

@Data
class Task {

    //任务唯一标识,可以根据业务,考虑替换目前以className为标记的实现
    private String taskKey;

    //任务类名,类名应该以下拉的方式呈现,供前端选择
    private String jobClassName;

    //cron表达式,需要校验
    private String cronExpression;

    //任务参数
    private String param;
}

/**
 * 项目重启时,需要将已经持久化的任务全部重新托管给Quartz,所以需要在项目启动后,对Quartz进行初始化
 */
@Order(100)
@Component
class QuartzTaskInitializer implements CommandLineRunner {

    @Resource
    private MyQuartzController myQuartzController;

    @Override
    public void run(String... args) throws Exception {
        //1.从数据库查询出所有未删除,且状态为已托管的任务记录列表
        List<Task> taskList = new ArrayList<>();
        //2.便利重新托管
        taskList.forEach(it -> {
            try {
                this.myQuartzController.deleteFromQuartz(it.getJobClassName());
                this.myQuartzController.addToQuartz(it.getJobClassName(), it.getCronExpression(), it.getParam());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

posted @ 2020-08-09 23:43  JaxYoun  阅读(211)  评论(0编辑  收藏  举报