springboot整合quartz实现定时任务的动态修改,启动,暂停等操作

  |   0 评论   |   0 浏览

什么是Quartz?

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

springboot整合Quartz定时调度框架

开发环境

  1. JDK版本1.8
  2. springboot版本:2.1.0
  3. 开发工具:IDEA

实现一个简单的定时任务

第一步 引入对应的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();
    }
}

最后运行项目查看效果

成功执行任务
png

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

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

第一步 创建一个定时任务相关实体类用于保存定时任务相关信息到数据库当中

public class QuartzBean {
    /** 任务id */
    private String  id;

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

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

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

    /** 任务运行时间表达式 */
    private String cronExpression;
    //省略getter setter
  }

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

public class QuartzUtils {

    /**
     * 创建定时任务 定时任务创建之后默认启动状态
     * @param scheduler   调度器
     * @param quartzBean  定时任务信息类
     * @throws Exception
     */
    public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean){
        try {
            //获取到定时任务的执行类  必须是类的绝对路径名称
            //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
            // 构建定时任务信息
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).build();
            // 设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
            // 构建触发器trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.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 quartzBean  定时任务信息类
     * @throws SchedulerException
     */
    public static void updateScheduleJob(Scheduler scheduler, QuartzBean quartzBean)  {
        try {
            //获取到对应任务的触发器
            TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
            //设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.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

public class MyTask1 extends QuartzJobBean {

    //验证是否成功可以注入service   之前在ssm当中需要额外进行配置
    @Autowired
    private AccountService service;
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Account account = new Account();
        account.setId(1);
        account = service.findByAccount(account);
        System.out.println(account.toString());
        //TODO 这里写定时任务的执行逻辑
        System.out.println("动态的定时任务执行时间:"+new Date().toLocaleString());
    }
}

新建一个测试Controller

@Controller
@RequestMapping("/quartz/")
public class QuartzController {
    //注入任务调度
    @Autowired
    private Scheduler scheduler;

    @RequestMapping("/createJob")
    @ResponseBody
    public String  createJob(QuartzBean quartzBean)  {
        try {
            //进行测试所以写死
            quartzBean.setJobClass("com.hjljy.blog.Quartz.MyTask1");
            quartzBean.setJobName("test1");
            quartzBean.setCronExpression("*/10 * * * * ?");
            QuartzUtils.createScheduleJob(scheduler,quartzBean);
        } 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(QuartzBean quartzBean)  {
        try {
            //进行测试所以写死
            quartzBean.setJobClass("com.hjljy.blog.Quartz.MyTask1");
            quartzBean.setJobName("test1");
            quartzBean.setCronExpression("10 * * * * ?");
            QuartzUtils.updateScheduleJob(scheduler,quartzBean);
        } catch (Exception e) {
            return "启动失败";
        }
        return "启动成功";
    }
}

然后在网页上输入对应URL进行暂停,启动,创建,修改,单次运行等操作就可以了。

第四步 总结

1 springboot2.0后默认添加了quartz的依赖,可以少些很多配置信息,只需要写好自己的任务类(需要实现job类)然后通过调度器scheduler添加任务就可以了。
2 通过@Bean注解简单创建定时任务的时候,直接写任务类的class就可以,但是通过scheduler的时候需要写绝对名称。
3 在quartz任务暂停之后再次启动时,会立即执行一次,在更新之后也会立即执行一次。
4 在springboot当中默认quartz线程池大小为10。
5 在启动项目初始化时需要将项目的定时任务也进行初始化。这样比较方便不用依次进行启动

参考资料

springboot整合Quartz定时任务: https://www.cnblogs.com/lic309/p/4089633.html
springboot官方手册:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/html/boot-features-quartz.html


标题:springboot整合quartz实现定时任务的动态修改,启动,暂停等操作
作者:hjljy
地址:https://www.hjljy.cn/articles/2019/01/23/1548228265862.html