美文网首页
Spring Boot整合Quartz

Spring Boot整合Quartz

作者: GIT提交不上 | 来源:发表于2020-07-01 00:00 被阅读0次

    一、Quartz简介

      Quartz是一个开源作业调度框架,其核心概念包括:

    • Job:表示一个工作,要执行的具体内容。
    • JobDetail:表示一个具体的可执行的调度程序,包含任务调度的方案和策略。
    • Trigger:表示一个调度参数的配置,表示什么时候去调度。
    • Scheduler:表示一个调度容器,当JobDetail和Trigger组合时方可进行调度。
    • JobDataMap:JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据(JobDetail & Trigger)。在Job执行时,JobExecutionContext中的JobDataMap是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值。
    图1-1 Quartz核心组件.png
    //JobDataMap使用
    .usingJobData("name", "luffy")
    .usingJobData("age", 18)
    
    /**
    * 获取JobDetail和Trigger创建时的JobDataMap
    */
    JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
    

      @DisallowConcurrentExecution:将该注解加到job类上,告诉Quartz不要并发地执行同一个job定义(这里指特定的job类)的多个实例。(针对JobDetail
      @PersistJobDataAfterExecution:将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据。(针对JobDetail
      Job.execute()方法中仅允许抛出一种类型的异常(包括RuntimeExceptions),即JobExecutionException。因此,你应该将execute方法中的所有内容都放到一个”try-catch"块中。job可以使用该异常告诉scheduler,你希望如何来处理发生的异常。
      SimpleTrigger:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。
      CronTrigger:使用Cron Expressions指定触发策略。
      TriggerListeners、JobListeners、SchedulerListeners查看对应接口。
      Job Stores:切勿在代码中直接使用JobStore实例。

    Quartz参考文档
    Quartz配置参考

    二、Spring Boot整合Quartz

      本文完整示例代码见

    https://github.com/just-right/quartz

      引入maven依赖:

     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    

      Quartz相关配置参考:

    spring-boot-2.0.3之quartz集成,不是你想的那样哦!

      自定义Job类实现execute方法,获取JobDetail和Trigger的dataMap属性。

    @DisallowConcurrentExecution
    @PersistJobDataAfterExecution
    public class LuffyJob implements MyJob {
        private Logger logger = LoggerFactory.getLogger(getClass());
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            /**
             * 获取JobDetail和Trigger创建时的JobDataMap
             */
            JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
            JobDataMap mergedJobDataMap = jobExecutionContext.getMergedJobDataMap();
            logger.info("执行定时任务!");
            jobDataMap.forEach((k, v) -> logger.info(k + ":" + v));
            mergedJobDataMap.forEach((k, v) -> logger.info(k + ":" + v));
        }
    }
    

      控制层传入Job和Trigger参数,开启调度器,创建JobDetai和Trigger。

    @PostMapping(value = "/startJob")
    public String startJob(@RequestBody StartJobDto dto) {
        String resInfo = null;
        Map<String,String> infoMap = new HashMap<>();
        infoMap.put("creator","luffy");
        JobDataMap dataMap = new JobDataMap(infoMap);
        try {
            //开启调度器
            scheduler.start();
            //创建JobDetail
            JobDetail jobDetail =  JobBuilder.newJob(getClass(dto.getJobClassName()).getClass())
                    .withIdentity(dto.getJobName(), dto.getJobGroupName())
                    .requestRecovery(true)
                    .usingJobData("name","jobdetal")
                    .usingJobData("age",2)
                    .requestRecovery()
                    .build();
    
            //创建CronScheduleBuilder
            CronScheduleBuilder scheduleBuilder =  CronScheduleBuilder.cronSchedule(dto.getCronExpression().trim());
            //创建触发器
            CronTrigger trigger =  TriggerBuilder.newTrigger()
                    .withIdentity("trigger:"+dto.getJobName(), dto.getJobGroupName())
                    .startNow()
                    .usingJobData("name","trigger")
                    .usingJobData("date",new Date().toString())
                    .withSchedule(scheduleBuilder)
                    .endAt(DateFormat.getDateTimeInstance().parse("2020-11-13 23:59:59"))
                    .modifiedByCalendar("Holidays")
                    .build();
            //调度器关联Job和Trigger
            HolidayCalendar cal = new HolidayCalendar();
            cal.addExcludedDate( DateFormat.getDateTimeInstance().parse("2020-11-13 23:59:59"));
            scheduler.addCalendar("Holidays",cal,false,false);
            scheduler.scheduleJob(jobDetail,trigger);
            resInfo = "success";
        } catch (Exception e) {
            resInfo = "error";
        }
        return resInfo;
    }
    

    参考链接一:SpringBootQuartz
    参考链接二:Quartz 教程
    参考链接三:Java任务调度框架Quartz教程
    参考链接四:Cron表达式在线

    三、异常、中断处理

    3.1 异常处理

      立即重新执行任务:

    @DisallowConcurrentExecution
    @PersistJobDataAfterExecution
    public class LuffyJob implements MyJob {
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            try {
               //do something
            } catch (Exception e) {
                JobExecutionException exception = new JobExecutionException(e);
                /**
                 * 工作立即重新开始
                 */
                exception.setRefireImmediately(true);
                throw exception;
            }
        }
    }
    

       立即停止所有相关这个任务的触发器:

    @DisallowConcurrentExecution
    @PersistJobDataAfterExecution
    public class LuffyJob implements MyJob {
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            try {
               //do something
            } catch (Exception e) {
                JobExecutionException exception = new JobExecutionException(e);
                /**
                 * 自动取消与此作业关联的所有触发器计划
                 */
                exception.setUnscheduleAllTriggers(true);
                throw exception;
            }
        }
    }
    

    Quartz:Quartz任务异常处理方式

    3.2 中断处理

       实现InterruptableJob接口,重写execute和interrupt方法即可。

    quartz2.3.0(七)调度器中断任务执行,手动处理任务中断事件

    四、测试

      前端传入Job类路径、jobName、jobGroupName和cronExpression。

    图4-1 Quartz请求测试.png

      每10秒打印一次dataMap信息,打印结果如下所示:

    图4-2 Quartz输出结果信息.png

    相关文章

      网友评论

          本文标题:Spring Boot整合Quartz

          本文链接:https://www.haomeiwen.com/subject/obdqqktx.html