spring boot + quartz定时任务框架入坑指南

quartz

Quartz是一个功能丰富的开源作业调度库,可以集成到几乎任何Java应用程序中

添加Maven依赖

        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.3version>
        dependency>
        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plusartifactId>
            <version>2.1.2version>
        dependency>

        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatisplus-spring-boot-starterartifactId>
            <version>1.0.4version>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-context-supportartifactId>
        dependency>
        <dependency>
            <groupId>org.quartz-schedulergroupId>
            <artifactId>quartzartifactId>
            <version>2.2.1version>
        dependency>

构建基本类

定时任务通用接口

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public interface BaseJob extends Job{
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException;
}

定时任务接口的实现类

import com.quartz.springquartz.task.BaseJob;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

import java.time.LocalDateTime;

public class TestJob implements BaseJob {

    public TestJob() {
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobKey key = jobDetail.getKey();
        System.out.println(key.getName()+"-"+key.getGroup()+"执行时间: " + LocalDateTime.now().toString());
    }
}

quartz的JAVA config bean注入

import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.quartz.*;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;


@Configuration
public class QuartzConfig {

    @Bean(name="SchedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setQuartzProperties(quartzProperties());
        return factory;
    }

    /*
     * quartz初始化监听器
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    /*
     * 通过SchedulerFactoryBean获取Scheduler的实例
     */
    @Bean(name="Scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }

    /**
     * 设置quartz属性,可以从properties配置中读取
     */
    public Properties quartzProperties() throws IOException {
        Properties prop = new Properties();
        prop.put("quartz.scheduler.instanceName", "ServerScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
        prop.put("org.quartz.scheduler.instanceId", "NON_CLUSTERED");
        prop.put("org.quartz.scheduler.jobFactory.class", "org.quartz.simpl.SimpleJobFactory");
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "5");
        return prop;
    }
}

操作定时任务的service类,就不写接口了直接实现,数据库dao和service自己实现,Task是我定义的pojo

import com.quartz.springquartz.entity.Task;
import com.quartz.springquartz.manager.TaskService;
import com.quartz.springquartz.task.BaseJob;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;


@Service
public class ScheduleJobService {
    @Autowired @Qualifier("Scheduler")
    private Scheduler scheduler;

    //自己选择所用的dao
    @Autowired
    TaskService taskService;

    public String addJob(Task task) throws Exception{
        // 启动调度器
        scheduler.start();

        //构建job信息
        JobDetail jobDetail = JobBuilder
                .newJob(getClass(task.getClassName()).getClass()).withIdentity(task.getName(), task.getGroup()).build();

        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());

        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getName(), task.getGroup())
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
            //taskService.insert(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return "success";
    }

    public JobDetail jobPause(String jobName, String jobGroupName) throws Exception
    {
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
        JobDetail detail = scheduler.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
        return detail;
    }

    public void jobreschedule(String jobName, String jobGroupName, String cronExpression) throws Exception
    {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            System.out.println("更新定时任务失败"+e);
        }
    }

    public static BaseJob getClass(String classname) throws Exception
    {
        Class class1 = Class.forName(classname);
        return (BaseJob)class1.newInstance();
    }
}

添加监听器,应用启动时,从数据库中读取定时任务并加入

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.quartz.springquartz.entity.Task;
import com.quartz.springquartz.manager.TaskService;
import com.quartz.springquartz.service.ScheduleJobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;

import java.util.List;

@Configuration
public class JobListener implements ApplicationListener<ContextRefreshedEvent>{

    @Autowired
    TaskService taskService;
    @Autowired
    ScheduleJobService scheduleJobService;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
        EntityWrapper ew = new EntityWrapper<>();
        ew.where("status = {0}",1);
        List tasks = taskService.selectList(ew);
        System.out.println("task size = "+tasks.size());
        try {
            for (Task task : tasks) {
                scheduleJobService.addJob(task);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

再写一个controller测试用,就可以玩去了

import com.quartz.springquartz.entity.Task;
import com.quartz.springquartz.service.ScheduleJobService;
import com.quartz.springquartz.task.BaseJob;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Map;


@RestController
@RequestMapping(value="/job")
public class TestController {

    //加入Qulifier注解,通过名称注入bean
    @Autowired @Qualifier("Scheduler")
    private Scheduler scheduler;
    @Autowired
    ScheduleJobService scheduleJobService;

    @RequestMapping("/add")
    public String addJob(@RequestBody Task task) throws Exception{
        scheduleJobService.addJob(task);
        return "success";
    }

    @PostMapping(value="/pause")
    public JobKey pausejob(@RequestBody Map map) throws Exception
    {
        JobDetail detail = scheduleJobService.jobPause((String)map.get("jobName"), (String)map.get("jobGroupName"));
        return detail.getKey();
    }

    @PostMapping(value="/edit")
    public String rescheduleJob(@RequestBody Map map) throws Exception
    {
        scheduleJobService.jobreschedule((String)map.get("jobName"),(String)map.get("jobGroupName"),(String)map.get("cronExpression"));
        return "success";
    }
}

总结

最初入门,quartz配置中的存储,分布式应用暂时没看,下篇文章再说,只实现了单机中定时任务的数据库持久化和动态添加

你可能感兴趣的:(spring boot + quartz定时任务框架入坑指南)