壹影博客.
我在下午4点钟开始想你
SpringBootQuartz实现动态定时任务配置
  • 2024-4-12日
  • 0评论
  • 237围观

SpringBootQuartz实现动态定时任务配置

Spring Boot集成Quartz实现定时任务的动态创建、启动、暂停、恢复、删除

什么是Quartz?
一个定时任务调度框架,简单易用,功能强大可以使实现定时任务的。 在项目开发过程当中,某些定时任务,可能在运行一段时间之后,就不需要了,或者需要修改下定时任务的执行时间等等。 需要在代码当中进行修改然后重新打包发布,很麻烦。使用Quartz来实现的话不需要重新修改代码而达到要求

本篇文章将带你用springboot整合Quartz定时调度框架

开发环境

 JDK版本1.8
 springboot版本:2.1.0
开发工具:IDEA

传统方式使用Quartz

  一、引入对应的jar
在springboot2.0后官方添加了Quartz框架的依赖,所以只需要在pom文件当中引入

      <!--引入quartz定时框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

二、创建一个定时任务
由于springboot2.0自动进行了依赖所以创建的定时任务类直接继承QuzrtzJobBean就可以了,新建一个定时任务类:MyTask

public class MyTask extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //TODO 这里写定时任务的执行逻辑
        System.out.println("简单的定时任务执行时间:"+new Date().toLocaleString());
    }
}

三、创建Quartz配置类将之前创建的定时任务添加到定时调度里面

@Configuration
public class QuartzConfig {
	//指定具体的定时任务类
    @Bean
    public JobDetail uploadTaskDetail() {
        return JobBuilder.newJob(MyTask.class).withIdentity("MyTask").storeDurably().build();
    }
 
    @Bean
    public Trigger uploadTaskTrigger() {
        //TODO 这里设定执行方式
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("*/5 * * * * ?");
        // 返回任务触发器
        return TriggerBuilder.newTrigger().forJob(uploadTaskDetail())
                .withIdentity("MyTask")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

传统方式总结:这种方式是写死在程序当中的,也存在修改不方便的情况!!!!!!

动态实现定时任务

实现定时调度任务的动态暂停,修改,启动,单次执行等操作

 第一步:创建一个定时任务相关实体类用于保存定时任务相关信息到数据库当中,由于这个实体类其实是与Quartz进行交互的所以我们可以命名为QuartzContext

//路径:com.xxxx.context.QuartzContext.java

import lombok.Data;
import java.util.Map;

@Data
public class QuartzContext {
    /** 任务id */
    private String  id;

    /** 任务名称 */
    private String jobName;

    /** 任务执行类 */
    private String jobClass;

    /** 任务状态 启动还是暂停*/
    private Integer status;

    /** 任务运行时间表达式 */
    private String cronExpression;

    private Map<String,Object> data;
    //省略getter setter
  }

第二步:创建定时任务暂停,修改,启动,单次启动工具类

//路径:com.xxx.utils.QuartzUtils.java;

import cn.hutool.json.JSONUtil;
import com.tron.context.QuartzContext;
import org.quartz.*;

import java.util.Map;

public class QuartzUtils {

    /**
     * 创建定时任务 定时任务创建之后默认启动状态
     * @param scheduler   调度器
     * @param quartzContext  定时任务信息类
     * @throws Exception
     */
    public static void createScheduleJob(Scheduler scheduler, QuartzContext quartzContext){
        try {
            //获取到定时任务的执行类  必须是类的绝对路径名称
            //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzContext.getJobClass());
            JobDataMap jobDataMap = new JobDataMap();
            Map<String, Object> data = quartzContext.getData();
            jobDataMap.putAll(data);

            // 构建定时任务信息
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzContext.getJobName()).usingJobData(jobDataMap).build();
            
            // 设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzContext.getCronExpression());
            // 构建触发器trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzContext.getJobName()).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (ClassNotFoundException e) {
            System.out.println("定时任务类路径出错:请输入类的绝对路径");
        } catch (SchedulerException e) {
            System.out.println("创建定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称暂停定时任务
     * @param scheduler  调度器
     * @param jobName    定时任务名称
     * @throws SchedulerException
     */
    public static void pauseScheduleJob(Scheduler scheduler, String jobName){
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("暂停定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称恢复定时任务
     * @param scheduler  调度器
     * @param jobName    定时任务名称
     * @throws SchedulerException
     */
    public static void resumeScheduleJob(Scheduler scheduler, String jobName) {
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("启动定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称立即运行一次定时任务
     * @param scheduler     调度器
     * @param jobName       定时任务名称
     * @throws SchedulerException
     */
    public static void runOnce(Scheduler scheduler, String jobName){
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("运行定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 更新定时任务
     * @param scheduler   调度器
     * @param quartzContext  定时任务信息类
     * @throws SchedulerException
     */
    public static void updateScheduleJob(Scheduler scheduler, QuartzContext quartzContext)  {
        try {
            //获取到对应任务的触发器
            TriggerKey triggerKey = TriggerKey.triggerKey(quartzContext.getJobName());
            //设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzContext.getCronExpression());
            //重新构建任务的触发器trigger
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            //重置对应的job
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            System.out.println("更新定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据定时任务名称从调度器当中删除定时任务
     * @param scheduler 调度器
     * @param jobName   定时任务名称
     * @throws SchedulerException
     */
    public static void deleteScheduleJob(Scheduler scheduler, String jobName) {
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("删除定时任务出错:"+e.getMessage());
        }
    }
}

第三步、创建一个定时任务和相关测试类。
新建一个定时任务MyTask1

//路径:com.xxx.task.MyTask1.java

//一个测试任务
@Component
public class MyTask1 extends QuartzJobBean {
 
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //如果你有参数的话 在JobDataMap 里面去取
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        // String account = (String)jobDataMap.get("account"); //测试的参数取值

        //TODO 这里写定时任务的执行逻辑
        System.out.println("动态的定时任务执行时间:"+new Date().toLocaleString());
    }
}

第四步、创建一个测试controller来对任务进行增删改查

//路径:com.xxx.controller.QuartzController.java

import com.tron.context.QuartzContext;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;

@Controller
@RequestMapping("/quartz/")
public class QuartzController {
    //注入任务调度
    @Autowired
    private Scheduler scheduler;
 
    @RequestMapping("/createJob")
    @ResponseBody
    public String  createJob(QuartzContext quartzContext)  {
        try {
            //进行测试所以写死
            quartzContext.setJobClass("com.xxx.task.MyTask1");
            quartzContext.setJobName("test1");
            quartzContext.setCronExpression("*/10 * * * * ?");

            //模拟传参
            Map<String,Object> map = new HashMap<>();
            map.put("account",account);
            map.put("privateKey",privateKey);
            map.put("amount",amount);
            quartzContext.setData(map);
            
            QuartzUtils.createScheduleJob(scheduler,quartzContext);
        } catch (Exception e) {
            return "创建失败";
        }
        return "创建成功";
    }
 
    @RequestMapping("/pauseJob")
    @ResponseBody
    public String  pauseJob()  {
        try {
            QuartzUtils.pauseScheduleJob (scheduler,"test1");
        } catch (Exception e) {
            return "暂停失败";
        }
        return "暂停成功";
    }
 
    @RequestMapping("/runOnce")
    @ResponseBody
    public String  runOnce()  {
        try {
            QuartzUtils.runOnce (scheduler,"test1");
        } catch (Exception e) {
            return "运行一次失败";
        }
        return "运行一次成功";
    }
 
    @RequestMapping("/resume")
    @ResponseBody
    public String  resume()  {
        try {
 
            QuartzUtils.resumeScheduleJob(scheduler,"test1");
        } catch (Exception e) {
            return "启动失败";
        }
        return "启动成功";
    }
 
    @RequestMapping("/update")
    @ResponseBody
    public String  update(QuartzContext quartzContext)  {
        try {
            //进行测试所以写死
            quartzContext.setJobClass("com.xxx.task.MyTask1");
            quartzContext.setJobName("test1");
            quartzContext.setCronExpression("10 * * * * ?");
            QuartzUtils.updateScheduleJob(scheduler,quartzContext);
        } catch (Exception e) {
            return "启动失败";
        }
        return "启动成功";
    }
}

恭喜你!利用SpringBootQuartz实现动态定时任务的配置,赶快启动项目试试吧

 by 壹影 ~

发表评论