zoukankan      html  css  js  c++  java
  • spring-boot Quartz 实践

    一、基本概念了解

      之前做自动化测试平台有个需求,就是系统在每天晚上定时去执行一个测试任务,执行完成后把这个测试结果通过邮件发送出去。要求定时任务是随时可配置,之前有过一个方案,就是在linux使用crontab定时请求系统的一个任务执行接口。虽然可以解决对应的问题,而且某些方面来讲简单粗暴,但是在定时器配置方面着实麻烦,想通过代码方面来解决,于是就考虑用quartz来解决。

      通过google大概了解一下quartz的基本概念,知道了quartz的一些基本元素(强烈建议大致了解下quartz的工作流程,之后再动手去实践,会少走很多弯路),quartz主要有以下三个元素构成:

      Scheduler:调度器或者说是容器,所有的任务和触发器都是在这个容器中进行注册。

      JobDetail:一个可执行的任务

      Trigger:任务的处触发条件

      工作流程主要是在将JobDetail 和 Trigger组合一起注册到Scheduler容器中,然后通过Scheduler依据Trigger来调度执行JobDetail的内容。

    二、简单例子

      按照上面的思想,我们做一个最简单的定时器任务,具体如下:

      1、创建一个可执行的任务

    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    
    /**
     * Created by tangrubei on 2018/3/30.
     */
    public class Myjob implements Job {
        @Override
        public void execute(JobExecutionContext context) {
    //        获取上下文内容
            String data = (String) context.getMergedJobDataMap().get("data");
    //        do something
            System.out.println(data);
    
        }
    }

      2、创建容器和触发器,并将任务和触发器一起注册到容器中

    import org.quartz.*;
    import org.quartz.impl.StdSchedulerFactory;
    
    /**
     * Created by tangrubei on 2018/3/30.
     */
    public class MyJobTest {
    
        public static void main(String[] args) throws SchedulerException, InterruptedException {
    //        创建容器工厂类
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    //        创建容器
            Scheduler scheduler = schedulerFactory.getScheduler();
    //        启动容器
            scheduler.start();
    //        创建一个可执行的工作任务
            JobDetail jobDetail = JobBuilder.newJob(Myjob.class).withIdentity("myfirstJob", "mygroup").build();
    //        创建一个触发器
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myfirstJobTriger", "mygroup")
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();
    //        设置任务的执行的上下文
            jobDetail.getJobDataMap().put("data", "my first job");
    //        讲任务和定时器注册到容器中
            scheduler.scheduleJob(jobDetail, trigger);
        }
    
    }

    三、项目实践:

      回到我们最初的需求中来,我们需要实现一个定时的组件,这个组件支持增加、删除、更新任务,同时在系统启动的时候,会自动到配置或者数据库中去load已经配置好的任务。

      依据上面的简单实例我们很容易做到从配置中动态增加、删除、更新任务,只是在项目启动的时候去执行这些东西还没有实现,这个时候稍微google一下就能发现我们只要实现ApplicationListener接口就可以实现项目启动的时候就加载这个定时器,直接上代码(我这边的需求是一个任务对应一个触发器,如果一个触发器对应多个任务的话,删除和更新就不能按照我这个来写了)

    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.event.ContextRefreshedEvent;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * Created by tangrubei on 2017/2/10.
     */
    
    public class QuartzManagerComponent implements ApplicationListener<ContextRefreshedEvent> {
    
    
        private Scheduler scheduler;
    
    
        private final String groupName = "groupExecute";
    
    //    注入工厂类
        @Autowired
        private SchedulerFactory schedulerFactory;
    
    
    //    系统启动时执行
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            try {
    //            初始化容器
                scheduler = schedulerFactory.getScheduler();
    //            启动容器
                scheduler.start();
    //            初始job上下文和注册任务,这里可以改为从数据库或者配置里获取任务,动态加载
                Map datamap = new HashMap();
                datamap.put("data","my job time");
                this.addJob("myjob","0/5 * * * * ?",MyJob.class,datamap);
    //
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    
    
    //  新增任务
        pbulic void addJob(String jobName, String jobTime, Class jobClassz, Map<String, Object> dataMap) throws SchedulerException {
            JobDetail job = JobBuilder.newJob(jobClassz).withIdentity(jobName, groupName).build();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            if (dataMap != null) {
                dataMap.forEach((k, v) -> {
                    job.getJobDataMap().put(k, v);
                });
            }
            scheduler.scheduleJob(job, trigger);
        }
    
    //  删除任务
        public void deleteJob(String jobName) throws SchedulerException {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            if (triggerKey != null) {
    //            暂停定时器
                scheduler.pauseTrigger(triggerKey);
    //            删除定时器
                scheduler.unscheduleJob(triggerKey);
                JobKey jobKey = JobKey.jobKey(jobName, groupName);
    //            删除任务
                scheduler.deleteJob(jobKey);
            }
        }
    
    //  更新任务
        public void updateJob(String jobName, String jobTime, Class classz, Map<String, Object> dataMap) throws SchedulerException {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            this.deleteJob(jobName);
            this.addJob(jobName, jobTime, classz, dataMap);
        }
    
    
    }

    源代码地址

      

      

      

  • 相关阅读:
    [ Luogu 3398 ] 仓鼠找sugar
    [ JLOI 2014 ] 松鼠的新家
    AtcoderGrandContest 005 F. Many Easy Problems
    Codeforces 388 D. Fox and Perfect Sets
    Codeforces 1037 H. Security
    「学习笔记」wqs二分/dp凸优化
    「NOI2017」游戏
    「SCOI2014」方伯伯的商场之旅
    「SCOI2015」情报传递
    「SCOI2016」美味
  • 原文地址:https://www.cnblogs.com/rubeitang/p/8677755.html
Copyright © 2011-2022 走看看