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);
    }


}

 

源代码地址

 

  

  

  

posted @ 2018-03-30 17:59  soultank  阅读(149)  评论(0编辑  收藏  举报