美文网首页
SpringBoot 基于Quartz的任务调度

SpringBoot 基于Quartz的任务调度

作者: 码农家的蜗牛 | 来源:发表于2020-02-28 15:37 被阅读0次

一. 什么是 SpringBootQuartz ?

Quartz 是一个任务调度工具包, 能够很自由的处理添加和维护基于单次 或者 cron表达式的任务.

说明: 本文档是基于 SpringBoot 2.x

二. pom.xml 引入依赖包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

三. 关键配置类

package com.example.quartz.config;

import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Description:
 * @Author: ZhangLuo
 */
@Configuration
public class SchedulerAutoConfiguration {

    /**
     * Spring提供的处理任务的线程池, 和 JDK 提供的 ThreadPoolExecutor 有所区别
     * @return
     */
    @Bean("executor")
    public Executor taskExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);//核心池大小
        executor.setMaxPoolSize(100);//最大线程数
        executor.setQueueCapacity(1000);//队列程度
        executor.setKeepAliveSeconds(1000);//线程空闲时间
        executor.setThreadNamePrefix("scheduler-");//线程前缀名称
        /**
         * 拒绝策略:
         * AbortPolicy:用于被拒绝任务的处理程序,它将抛出RejectedExecutionException
         *
         * CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务。
         *
         * DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试execute。
         *
         * DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//配置拒绝策略
        return executor;
    }

    /**
     * 调度工厂
     * @return
     */
    @Bean(name="schedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executor") Executor executor) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setAutoStartup(true);
        //这里如果不配置任务池,它就会默认加载SimpleThreadPool
        factory.setTaskExecutor(executor);
        return factory;
    }

    /**
     * 调度员
     * @return
     */
    @Bean(name="scheduler")
    public Scheduler scheduler(@Qualifier("schedulerFactory") SchedulerFactoryBean factoryBean) {
        return factoryBean.getScheduler();
    }
}

四. 一个简单的任务类

package com.example.quartz.job;

import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * @Description:
 * @Author: ZhangLuo
 */
@Slf4j
public class SimpleJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info("任务被触发...");
    }
}

五. 任务调度服务接口

package com.example.quartz.service;

/**
 * @Description:
 * @Author: ZhangLuo
 */
public interface JobSchedulerService {

    /**
     * 功能描述: 添加简单任务(单次)
     *   可以自定义一个任务信息对象,然后从信息对象中获取参数创建简单任务
     * @param executeDate 单次任务的执行时间
     */
    void addSimpleJob(Date executeDate);

    /**
     * 功能描述: 添加定时任务
     * 可以自定义一个任务信息对象,然后从信息对象中获取参数创建定时任务
     * @param cronExpression cron表达式字符串
     */
    void addCronJob(String cronExpression);

    /**
     * 功能描述: 修改任务Trigger,即修改任务的定时机制(仅支持表达式任务)
     * @param cronExpression cron表达式字符串
     */
    void modifyCronJob(String cronExpression);

    /**
     * 功能描述: 暂停任务,只支持定时任务的暂停,不支持单次任务,单次任务需要interrupt
     * @param
     */
    void pauseCronJob();

    /**
     * 功能描述: 从暂停状态中恢复定时任务运行(仅支持表达式任务)
     * @param
     */
    void resumeCronJob();

    /**
     * 功能描述: 删除任务(单次 或 表达式任务)
     * @param
     */
    void deleteJob();
}

六. 服务实现类

package com.example.quartz.service.impl;

import com.example.quartz.job.SimpleJob;
import com.example.quartz.service.JobSchedulerService;
import com.example.quartz.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;

/**
 * @Description: 任务调度实现类
 * @Author: ZhangLuo
 */
@Slf4j
@Service
public class JobSchedulerServiceImpl implements JobSchedulerService {

    /**
     * 任务调度员
     */
    @Autowired
    @Qualifier("scheduler")
    private Scheduler scheduler;

    /**
     * 添加单次任务
     */
    @Override
    public void addSimpleJob(Date executeDate) {
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("testJob01", "testJob")
                .build();
        SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .withIdentity("testTrigger01", "testTrigger")
                .startAt(executeDate)
                .build();
        try {
            scheduler.scheduleJob(jobDetail, simpleTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加循环任务
     */
    @Override
    public void addCronJob(String cronExpression) {
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("testJob01", "testJob")
                .build();
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().
                withIdentity("cronTrigger01", "cronTrigger")
                .withSchedule(scheduleBuilder)
                .build();
        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改定时任务
     */
    @Override
    public void modifyCronJob(String cronExpression) {
        TriggerKey oldKey = new TriggerKey("cronTrigger01", "cronTrigger");
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().
                withIdentity("cronTrigger01", "cronTrigger")
                .withSchedule(scheduleBuilder)
                .build();
        try {
            scheduler.rescheduleJob(oldKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停任务
     */
    @Override
    public void pauseCronJob() {
        JobKey jobKey = new JobKey("testJob01", "testJob");
        try {
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (ObjectUtils.isEmpty(jobDetail)) {
                System.out.println("没有这个job");
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复任务运行
     */
    @Override
    public void resumeCronJob() {
        JobKey jobKey = new JobKey("testJob01", "testJob");
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除任务
     */
    @Override
    public void deleteJob() {
        JobKey jobKey = new JobKey("testJob01", "testJob");
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

七. 添加接口测试服务类

package com.example.quartz.controller;

import com.example.quartz.service.JobSchedulerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description:
 * @Author: ZhangLuo
 */
@RestController
public class QuartzController {

    @Autowired
    private JobSchedulerService schedulerService;

    /**
     * 启动单次任务
     * @param dateStr
     * @return
     */
    @GetMapping("/simpleJob")
    public String simpleJob(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date executeDate = null;
        try {
            executeDate = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // 测试, 就不考虑异常情况了
        schedulerService.addSimpleJob(executeDate);
        return "ok";
    }

    /**
     * 添加表达式任务
     * @param cronExpression
     * @return
     */
    @GetMapping("/addCronJob")
    public String addCronJob(String cronExpression) {
        schedulerService.addCronJob(cronExpression);
        return "ok";
    }

    /**
     * 修改表达式任务
     */
    @GetMapping("/modifyCronJob")
    public String modifyCronJob(String cronExpression) {
        schedulerService.modifyCronJob(cronExpression);
        return "ok";
    }

    /**
     * 暂停任务
     * @return
     */
    @GetMapping("/pauseCronJob")
    public String pauseCronJob() {
        schedulerService.pauseCronJob();
        return "ok";
    }

    /**
     * 恢复任务
     * @return
     */
    @GetMapping("/resumeCronJob")
    public String resumeCronJob() {
        schedulerService.resumeCronJob();
        return "ok";
    }

    /**
     * 删除单次任务
     * @return
     */
    @GetMapping("delCronJob")
    public String delCronJob() {
        schedulerService.deleteJob();
        return "ok";
    }
}

大功告成, 一切搞定, 根据服务实现类里的参数, 自定义数据库数据结构即可, 就可以应用到实际生产中了.

相关文章

网友评论

      本文标题:SpringBoot 基于Quartz的任务调度

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