SpringBoot整合Quartz实现动态定时任务

1、增加依赖

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

<!-- json 工具 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>xxx</version>
</dependency>

 

2、application.yml 文件配置

 
# 引入 数据库的相关配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://local:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true
    username: root
    password: abc123
  #配置 quartz
  quartz:
    #初始化数据库脚本路径,默认使用classpath:org/quartz/impl/jdbcjobstore/tables_@@platform@@.sql路径下的脚本
    #注意,放置的是 spring.quartz 下面
    #持久化到数据库方式
    job-store-type: jdbc
    # 初始化Quartz表结构,项目第一次启动配置程always,然后改成never 否则已生成的job会被初始化掉
    initialize-schema: never
    properties:
      org:
        quartz:
          scheduler:
            instanceName: MyScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true

 

3、启动执行,数据库默认生成,后续将always改为never,不然插入的任务数据会被清空

 4、业务代码实现定时任务

4.1、实体类

import lombok.Data;

import java.io.Serializable;

@Data
public class QuartzBean implements Serializable {
    /**
     * 任务id
     */
    private String id;
    
    /**
     * 任务名称
     */
    private String jobName;
    
    /**
     * 任务执行类
     */
    private String jobClass;
    
    /**
     * 组名
     */
    private String groupName;
    
    /**
     * 任务 参数信息
     */
    private String jobParam;
    
    /**
     * 任务状态 启动还是暂停
     */
    private Integer status;
    
    /**
     * 任务运行时间表达式
     */
    private String cronExpression;
}

4.2、工具类

import com.alibaba.fastjson.JSON;
import com.nwcs.ioa.xigma.wf.dto.QuartzBean;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * 任务工具类
 *
 * @author yuejianli
 * @date 2023-01-04
 */
public class QuartzUtils {
    /**
     * 获取所有的定时任务
     *
     * @throws Exception
     */
    public static List<QuartzBean> getAllJob(Scheduler scheduler) {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        List<QuartzBean> jobList = new ArrayList();
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    QuartzBean job = new QuartzBean();
                    job.setJobName(jobKey.getName());
                    job.setGroupName(jobKey.getGroup());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setStatus(Trigger.TriggerState.NORMAL.equals(triggerState) ? 1 : 0);
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.setCronExpression(cronExpression);
                    }
                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                    JobDataMap jobDataMap = jobDetail.getJobDataMap();
                    String[] keys = jobDataMap.getKeys();
                    if (keys != null && keys.length > 0) {
                        Map<String, String> paramMap = new HashMap<>(keys.length, 1.0f);
                        for (String key : keys) {
                            paramMap.put(key, jobDataMap.get(key).toString());
                        }
                        String paramStr = JSON.toJSONString(paramMap);
                        job.setJobParam(paramStr);
                    }
                    Class<? extends Job> jobClass = jobDetail.getJobClass();
                    job.setJobClass(jobClass.getName());
                    jobList.add(job);
                }
            }
            
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }
    
    /**
     * 创建定时任务 定时任务创建之后默认启动状态
     *
     * @param scheduler  调度器
     * @param quartzBean 定时任务信息类
     * @throws Exception
     */
    public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean) {
        try {
            //获取到定时任务的执行类  必须是类的绝对路径名称
            //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
            // 构建定时任务信息
            JobBuilder jobBuilder = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName(), quartzBean.getGroupName());
            
            // 设置参数
            Map<String, String> paramHashMap = JSON.parseObject(quartzBean.getJobParam(), HashMap.class);
            if (!ObjectUtils.isEmpty(paramHashMap)) {
                paramHashMap.forEach(
                        (param, paramValue) -> {
                            jobBuilder.usingJobData(param, paramValue);
                        }
                );
            }
            JobDetail jobDetail = jobBuilder
                    .storeDurably()
                    .build();
            // 设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
            // 构建触发器trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (ClassNotFoundException e) {
            System.out.println("定时任务类路径出错:请输入类的绝对路径");
        } catch (SchedulerException e) {
            System.out.println("创建定时任务出错:" + e.getMessage());
        }
    }
    
    /**
     * 根据任务名称暂停定时任务
     *
     * @param scheduler  调度器
     * @param jobKeyName 定时任务名称
     * @throws SchedulerException
     */
    public static void pauseScheduleJob(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1], jobNameGroupArr[0]);
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("暂停定时任务出错:" + e.getMessage());
        }
    }
    
    /**
     * 根据任务名称恢复定时任务
     *
     * @param scheduler  调度器
     * @param jobKeyName 定时任务名称
     * @throws SchedulerException
     */
    public static void resumeScheduleJob(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1], jobNameGroupArr[0]);
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("启动定时任务出错:" + e.getMessage());
        }
    }
    
    /**
     * 根据任务名称立即运行一次定时任务
     *
     * @param scheduler  调度器
     * @param jobKeyName 定时任务名称
     * @throws SchedulerException
     */
    public static void runOnce(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1], jobNameGroupArr[0]);
        try {
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("运行定时任务出错:" + e.getMessage());
        }
    }
    
    /**
     * 更新定时任务
     *
     * @param scheduler  调度器
     * @param quartzBean 定时任务信息类
     * @throws SchedulerException
     */
    public static void updateScheduleJob(Scheduler scheduler, QuartzBean quartzBean) {
        deleteScheduleJob(scheduler, quartzBean.getGroupName() + "." + quartzBean.getJobName());
        createScheduleJob(scheduler, quartzBean);
    }
    
    /**
     * 根据定时任务名称从调度器当中删除定时任务
     *
     * @param scheduler  调度器
     * @param jobKeyName 定时任务名称
     * @throws SchedulerException
     */
    public static void deleteScheduleJob(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1], jobNameGroupArr[0]);
        try {
            if (ObjectUtils.isEmpty(jobKey)) {
                return;
            }
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("删除定时任务出错:" + e.getMessage());
        }
    }
}

 

 

4.3、控制类

import xx.entity.QuartzBean;
import xx.exception.BizException;
import xx.utils.QuartzUtils;
import xx.web.Result;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.quartz.Scheduler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@Tag(name = "quartz任务", description = "任务相关接口")
@RestController
@RequestMapping("/common/quartz/")
public class ScheduledController {
    
    
    /**
     * 注入任务调度
     */
    @Resource
    private Scheduler scheduler;
    
    @RequestMapping("get-all")
    public Result<?> getAll() {
        try {
            return new Result<>().ok(QuartzUtils.getAllJob(scheduler));
        } catch (Exception e) {
            throw new BizException("quartz-error-10001", new String[]{e.getMessage()});
        }
    }
    
    /**
     * 创建任务
     */
    @RequestMapping("create-job")
    public Result<?> createJob(@RequestBody QuartzBean quartzBean) {
        try {
            QuartzUtils.createScheduleJob(scheduler, quartzBean);
        } catch (Exception e) {
            throw new BizException("quartz-error-10002", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务创建成功");
    }
    
    @RequestMapping("pause-job")
    public Result<?> pauseJob(@RequestParam(name = "job-name") String jobName) {
        try {
            QuartzUtils.pauseScheduleJob(scheduler, jobName);
        } catch (Exception e) {
            throw new BizException("quartz-error-10003", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务暂停成功");
    }
    
    @RequestMapping("run-once")
    public Result<?> runOnce(@RequestParam(name = "job-name") String jobName) {
        try {
            QuartzUtils.runOnce(scheduler, jobName);
        } catch (Exception e) {
            throw new BizException("quartz-error-10004", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务运行一次成功");
    }
    
    /**
     * 重启任务(恢复定时任务)
     */
    @RequestMapping("resume")
    public Result<?> resume(@RequestParam(name = "job-name") String jobName) {
        try {
            QuartzUtils.resumeScheduleJob(scheduler, jobName);
        } catch (Exception e) {
            throw new BizException("quartz-error-10005", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务恢复定时任务成功");
    }
    
    /**
     * 删除任务
     */
    @RequestMapping("/delete")
    public Result<?> delete(@RequestParam(name = "job-name") String jobName) {
        try {
            QuartzUtils.deleteScheduleJob(scheduler, jobName);
        } catch (Exception e) {
            throw new BizException("quartz-error-10006", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务删除任务成功");
    }
    
    
    /**
     * 更新任务
     */
    @RequestMapping("/update")
    public Result<?> update(@RequestBody QuartzBean quartzBean) {
        try {
            QuartzUtils.updateScheduleJob(scheduler, quartzBean);
        } catch (Exception e) {
            throw new BizException("quartz-error-10007", new String[]{e.getMessage()});
        }
        return new Result<>().ok("Quartz任务更新成功");
    }
}

 

4.4、空参数任务DEMO

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

@Slf4j
public class MyTask extends QuartzJobBean {
    
    
    @Override
    protected void executeInternal(JobExecutionContext context) {
        log.info("空参数任务 {}", context.getJobDetail().getKey());
    }
}

 

4.5、有参数任务DEMO

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

@Slf4j
public class MyTask extends QuartzJobBean {
    
    
    @Override
    protected void executeInternal(JobExecutionContext context) {
        log.info("InterfaceLogAlertTask {}", context.getJobDetail().getKey());
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        log.info("InterfaceLogAlertTask jobDataMap {}", JSON.toJSONString(jobDataMap));
        String start_date = jobDataMap.get("start_date").toString();
        String end_date = jobDataMap.get("end_date").toString();
        if ((jobDataMap.containsKey("start_date") && !StringUtils.isNullOrEmpty(start_date)) && (jobDataMap.containsKey("end_date") && !StringUtils.isNullOrEmpty(end_date))) {
            interfaceLogService.syncAlert(start_date, end_date);
            return;
        }
        interfaceLogService.syncAlert(null, null);
    }
}

 

 

 

测试结果:

 

 

 

 

 

 

 

 

 

 

posted @ 2024-02-21 15:43  ToDarcy  阅读(714)  评论(0编辑  收藏  举报