当前位置: 首页 > news >正文

springboot+mybatis+mysql+Quartz实现任务调度(定时任务,实现可配置)

一.有关于Quartz

三大核心类 Scheduler(调度器),Trigger(触发器),JObDetail(作业类)。Trigger指定JObDetail什么时候发布任务。

1.Quartz 简介
Quartz 是 OpenSymphony 开源组织在 Job Scheduling 领域又一个开源项目,是完全由 Java 开发的一个开源任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。 Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中,它提供了巨大的灵活性而不牺牲简单性

当定时任务愈加复杂时,使用 Spring 注解 @Schedule 已经不能满足业务需要

在项目开发中,经常需要定时任务来帮助我们来做一些内容,如定时派息、跑批对账、将任务纳入日程或者从日程中取消,开始,停止,暂停日程进度等。SpringBoot 中现在有两种方案可以选择,第一种是 SpringBoot 内置的方式简单注解就可以使用,当然如果需要更复杂的应用场景还是得 Quartz 上场,Quartz 目前是 Java 体系中最完善的定时方案

2.Quartz 优点

  • 丰富的 Job 操作 API
  • 支持多种配置
  • SpringBoot 无缝集成 支持持久化
  • 支持集群
  • Quartz还支持开源,是一个功能丰富的开源作业调度库,可以集成到几乎任何 Java 应用程序中

3.核心概念

  • Scheduler:Quartz 中的任务调度器,通过 Trigger 和 JobDetail
    可以用来调度、暂停和删除任务。调度器就相当于一个容器,装载着任务和触发器,该类是一个接口,代表一个 Quartz的独立运行容器,Trigger 和 JobDetail 可以注册到 Scheduler 中,两者在 Scheduler中拥有各自的组及名称,组及名称是 Scheduler 查找定位容器中某一对象的依据,Trigger 的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和 Trigger 的组和名称相同,因为它们是不同类型的)

  • Trigger:Quartz中的触发器,是一个类,描述触发 Job 执行的时间触发规则,主要有 SimpleTrigger 和
    CronTrigger 这两个子类。当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger 是最适合的选择;而
    CronTrigger 则可以通过 Cron 表达式定义出各种复杂时间规则的调度方案:如工作日周一到周五的 15:00 ~
    16:00 执行调度等

  • JobDetail:Quartz 中需要执行的任务详情,包括了任务的唯一标识和具体要执行的任务,可以通过 JobDataMap
    往任务中传递数据 Job:Quartz 中具体的任务,包含了执行任务的具体方法。是一个接口,只定义一个方法 execute()
    方法,在实现接口的 execute() 方法中编写所需要定时执行的 Job

4.简易理解

  • job:任务 - 你要做什么事
  • Trigger:触发器 - 你什么时候去做
  • Scheduler:任务调度 - 你什么时候需要做什么事

在这里插入图片描述
在这里插入图片描述
5.Cron 表达式
Cron 表达式是一个字符串,包括 6~7 个时间元素,在 Quartz 中可以用于指定任务的执行时间

6.Cron 语法
Seconds Minutes Hours DayofMonth Month DayofWeek
秒 分钟 小时 日期天/日 日期月份 星期

7.在线 Cron 表达式生成器
其实 Cron 表达式无需多记,需要使用的时候直接使用在线生成器就可以了,地址:https://cron.qqe2.com/

二.springboot+Quartz具体实现

效果图及项目结构
在这里插入图片描述
在这里插入图片描述

1.创建一个springboot项目项目
选择相关的依赖包
在这里插入图片描述

在这里插入图片描述
2.maven依赖包

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

或者

<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.2</version>
</dependency>

  或者 (如果启动项目后,不加载QZ的话,用下面的依赖)
  
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
    <version>2.3.2.RELEASE</version>
</dependency>

3.yml配置文件

server.port=8087

# mysql 数据库连接
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://192.158.58.100:3306/springboot?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&autoReconnect=true
spring.datasource.username =hadoop
spring.datasource.password =root
spring.datasource.hikari.max-lifetime=120000

#druid 连接池配置
spring.datasource.druid.initial-size=3
spring.datasource.druid.min-idle=3
spring.datasource.druid.max-active=10
spring.datasource.druid.max-wait=60000

hibernate.node.name=node5

#整合mybatis
#给pojo实体类起别名
#mybatis.type-aliases-package=com.kuang.pojo
#接口的配置文件的位置 我这里接口配置文件是UserMapper.xml 如下图所示
mybatis.mapper-locations=classpath:mapper/*.xml

#打印sql语句-打印接口mapper中的
logging.level.com.tject.mapper=debug

#开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true
#打印mapper.xml配置文件中的sql语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#
#如果数据库中没有这个表 则根据entity直接创建
#################
###Spring jpa
##################

spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto = update

##自动建表通过以下策略来映射
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

4.新建任务表实体类SchedulerJobInfo

/**
*@descriprion: 定时任务-实体类
*@author: xujirong
*@date: 2022/8/29 21:43
*/
@Data
public class SchedulerJobInfo {

	private String id;

	private String version="1.0";


	private Date createTime=new Date();
	/**任务英文名称*/
	private String jobName;
	/**任务中文名称*/
	private String chineseName;
	private String jobBean;
	/**定时任务所属组*/
	private String jobGroup;
	/**cron表达式*/
	private String cron;
	private String status;
	private String remark;
	private String node;
	private String override;
    private String type;
    private String executorName;
    private String executorParam;
    private String mchId;
    private String mchPassword;
    private String v3Password;
    private String appId;
    private String mchApiSerial;
    private String shellString;
    private String sqlCode;
    private String sqlParam;
    private String isDownloadHdfs;
    private String isDownloadDb;
    private String periods;
}

5.新建接口注解CronJob

/**
 * @belongProject:定时任务-接口注解类
 * @belongPackage:com.tjetc.annotation
 * @author:xujirong
 * @dscription:TODO
 * @date:2022-09-02 22:16
 * @version:1.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CronJob {

    /**任务英文名称*/
    String beanName() default "";
    /**任务中文名称*/
    String chineseName() default "";
    /**cron表达式*/
    String cron() default "";
    /**定时任务所属组*/
    String group() default "";
    /**定时任务节点*/
    String node() default "node5";
}

6.新建InitRunner(初始化定时任务)

/**
 * @belongProject:项目启动时-加载定时任务
 * @belongPackage:com.tjetc.scheduler
 * @author:xujirong
 * @dscription: Trigger:触发器,Job:任务,Scheduler:调度器
 * @date:2022-09-02 22:38
 * @version:1.0
 */
@Component
@Order(value = 1)   //执行顺序控制
public class InitRunner implements ApplicationRunner {

    Logger logger = LoggerFactory.getLogger(InitRunner.class);

    /**
     * ApplicationContext是Spring中的核心接口和容器,
     * 允许容器通过应用程序上下文环境创建、获取、管理bean。
     * 在构建容器的时候,创建对象采用的策略是立即加载的方式,
     * 即只要一读取完配置文件就立即创建配置文件中配置的对象
     */
    @Autowired
    private ApplicationContext applicationContext;

    /**增删改查调度表(业务系统)-在系统表中*/
    @Autowired
    private SchedulerJobService schedulerJobService;

    /**增删改查调度任务(框架系统)-Quartz框架中定义任务*/
    @Autowired
    private IQuartzServiceImpl iQuartzService;

    /**根据节点名称查询调度表中的任务*/
    @Value("${hibernate.node.name}")
    private String nodeName;

    /**
    *@descriprion: 项目启动run方法-初始化cron定时任务
    *@author: xujirong
    *@date: 2022/9/3 13:01
    *@return: void
    */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //ApplicationArguments:应用程序启动参数

        //若SpringUtils中的ApplicationContext为空,则通过注解注入bean的方式重新赋值
        if (SpringUtils.getApplicationContext()==null){
            SpringUtils.setApplicationContext(applicationContext);
        }

        loadSchedulerCron();


        List<Map<String, Object>> mapNodeList = schedulerJobService.selectSchedulerByNode(nodeName);
        System.out.println("mapList.size() = " + mapNodeList.size());

        arrowFunction(mapNodeList);

        //遍历所有系统定义的任务,添加到加到Quartz框架中
        for (Map<String, Object> map : mapNodeList) {

        logger.info("添加的定时任务->job_name="+map.get("job_name")+",job_group="+map.get("job_group")+",cron="+map.get("cron")+",job_bean="+map.get("job_bean"));
        iQuartzService.addJob((String)map.get("job_name"),
                            (String)map.get("job_group"),
                            (String)map.get("cron"),
                            (String)map.get("job_bean"),"job_param_"+ UUID.randomUUID().toString().substring(0,6));

        }

    }

    /**
    *@descriprion: 加载项目中自定义的-定时任务
    *@author: xujirong
    *@date: 2022/9/3 20:25
    *@return: void
    */
    public void loadSchedulerCron(){
        //获取被@Cron注解定义的任务-集合
        Map<String, Object> objectMap = SpringUtils.getApplicationContext().getBeansWithAnnotation(CronJob.class);
        for (Object k:objectMap.keySet()){

            Object o = objectMap.get(k);

            //校验被注解@Cron的类是否为任务调度类(继承QuartzJobBean)
            if (o instanceof QuartzJobBean){
                //获取定时任务对象
                CronJob annotation = AopUtils.getTargetClass(o).getAnnotation(CronJob.class);


                //校验cron表达式的有效性
                if(CronExpression.isValidExpression(annotation.cron())){
                    String beanName = annotation.beanName();
                    //判断任务是否已存在
                    Map<String,Object> map = schedulerJobService.queryByBeanName(beanName);

                    if (map==null || map.size()==0){
                        SchedulerJobInfo schedulerJobInfo = new SchedulerJobInfo();

                        schedulerJobInfo.setChineseName(annotation.chineseName());
                        schedulerJobInfo.setJobBean(annotation.beanName());
                        schedulerJobInfo.setJobGroup(annotation.group());
                        schedulerJobInfo.setCron(annotation.cron());
                        schedulerJobInfo.setNode(annotation.node());

                        //保存新增任务
                        //schedulerJobService.addJob(schedulerJobInfo);

                    }
                }else {
                    logger.info("表达式->"+annotation.cron()+"有误");
                }

            }
        }

    }

    /**
    *@descriprion: 箭头函数(arrowFunction)的使用
    *@author: xujirong
    *@date: 2022/9/3 23:05
    *@return:
    */
    public void arrowFunction(List<Map<String, Object>> list){

        //以下则-得到一个,以job_name为key的Map为value的Map对象
        Map<String, Map<String, Object>> oldMaps =
                list.stream().filter(item ->{
                    if("test".equals(item.get("job_group"))){
                        return true; //留下
                    }
                    return false;
                }).collect(Collectors.toMap(obj -> ((Map) obj).get("job_name").toString(), obj -> obj));

        System.out.println("oldMaps = " + oldMaps);


    }
}

7.新建SpringUtils-获取上下文对象-进而获取想要的bean

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.utils
 * @author:xujirong
 * @dscription:TODO
 * @date:2022-08-28 20:10
 * @version:1.0
 */
public class SpringUtils {

    /**
     * ApplicationContext是Spring中的核心接口和容器,
     * 允许容器通过应用程序上下文环境创建、获取、管理bean。
     * 在构建容器的时候,创建对象采用的策略是立即加载的方式,
     * 即只要一读取完配置文件就立即创建配置文件中配置的对象
     */
    private static ApplicationContext applicationContext;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }
}

8.新建SchedulerJobService接口

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.service
 * @author:xujirong
 * @dscription:任务调度-任务接口
 * @date:2022-08-29 21:44
 * @version:1.0
 */
public interface SchedulerJobService {
    /**
    *@descriprion: 查询所有定时任务
    *@author: xujirong
    *@date: 2022/8/29 21:45
    *@return: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
    */
    List<Map<String,Object>> selectSchedulerJobAll();

    /**
    *@descriprion: 根据node节点查询任务
    *@author: xujirong
    *@date: 2022/9/3 14:37
    *@return: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
    */
    List<Map<String, Object>> selectSchedulerByNode(String nodeName);

    /**
     *@descriprion: 根据任务beanName名称查询任务
     *@author: xujirong
     *@date: 2022/9/3 14:37
     *@return: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     */
    Map<String, Object> queryByBeanName(String beanName);
}

9.新建SchedulerJobService 接口的实现类

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.service.impl
 * @author:xujirong
 * @dscription:TODO
 * @date:2022-08-29 21:44
 * @version:1.0
 */
@Scope("prototype")
@Service
public class SchedulerJobServiceImpl implements SchedulerJobService {

    @Autowired
    private SchedulerJobMapper schedulerJobMapper;

    @Override
    public List<Map<String, Object>> selectSchedulerJobAll() {
        return schedulerJobMapper.selectSchedulerJobAll();
    }

    @Override
    public List<Map<String, Object>> selectSchedulerByNode(String nodeName) {

        return schedulerJobMapper.selectSchedulerByNode(nodeName);
    }

    @Override
    public Map<String, Object> queryByBeanName(String beanName) {
        return schedulerJobMapper.queryByBeanName(beanName);
    }
}

10.新建schedulerJobMapper接口-实现和数据库表的数据交互

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.mapper
 * @author:xujirong
 * @dscription:TODO
 * @date:2022-08-29 21:46
 * @version:1.0
 */
@Repository
public interface SchedulerJobMapper {
    List<Map<String, Object>> selectSchedulerJobAll();

    List<Map<String, Object>> selectSchedulerByNode(String nodeName);

    Map<String, Object> queryByBeanName(String beanName);
}

11.新建SchedulerJobMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tjetc.mapper.SchedulerJobMapper">
    <select id="selectSchedulerJobAll" resultType="java.util.Map">
        select * from t_scheduler_job
    </select>

    <select id="selectSchedulerByNode" parameterType="string" resultType="java.util.Map">
        select * from t_scheduler_job where node=#{nodeName}
    </select>

    <select id="queryByBeanName" parameterType="string" resultType="java.util.Map">
        select * from t_scheduler_job where job_bean=#{beanName}
    </select>

</mapper>


12.新建IQuartzService任务调度接口(重点)

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.service
 * @author:xujirong
 * @dscription:调度任务接口
 * @date:2022-09-03 13:22
 * @version:1.0
 */
public interface IQuartzService {

    /**
     * 添加一个任务
     *
     * @param jobName      job的名称
     * @param jobGroupName job的组名称
     * @param jobTime      时间表达式 (这是每隔多少秒为一次任务)
     * @param runCount     运行的次数 (<0:表示不限次数)
     */
    public void addJob(String jobName, String jobGroupName, int jobTime,
                       int runCount,String beanName,Object jobParam) throws Exception;

    /**
     * 增加一个job
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     * @param jobTime      时间表达式 (如:0/5 * * * * ? )
     */
    public void addJob(String jobName, String jobGroupName, String jobTime,String beanName,Object jobParam) throws Exception;

    /**
     * 修改一个job任务
     *
     * @param jobName      名称
     * @param jobGroupName 组名
     * @param jobTime      job的Corn时间
     */
    public void updateJob(String jobName, String beanName, String jobGroupName, String jobTime, Object jobParam) throws  Exception;


    /**
     * 删除一个Job任务
     *
     * @param jobName      名称
     * @param jobGroupName 组名称
     */
    public void deleteJob(String jobName, String jobGroupName) throws  Exception;

    /**
     * 暂停一个Job任务
     *
     * @param jobName      名称
     * @param jobGroupName 组名
     */
    public void pauseJob(String jobName, String jobGroupName) throws  Exception;


    /**
     * 恢复一个任务
     *
     * @param jobName      名称
     * @param jobGroupName 组名
     */
    public void resumeJob(String jobName, String jobGroupName) throws Exception;


    /**
     * 立即执行一个任务
     *
     * @param jobName      名称
     * @param jobGroupName 组名
     */
    public void runAJobNow(String jobName, String jobGroupName) throws Exception;

    /**
     * 获取正在运行的JOB
     * @return
     * @throws Exception
     */
    public List<Map<String,Object>> getRunningJobList() throws Exception;

    /**
     * 获取所有的JOB
     * @return
     * @throws Exception
     */
    public List<Map<String,Object>> getAllJobList() throws Exception;
}

13.新建IQuartzService任务调度接口实现类IQuartzServiceImpl(重点)

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.hibernate02.service.impl
 * @author:xujirong
 * @dscription:调度任务实现类
 * @date:2022-08-28 14:18
 * @version:1.0
 */
@Slf4j
@Service
public class IQuartzServiceImpl implements IQuartzService {


    private Logger logger = LoggerFactory.getLogger(IQuartzServiceImpl.class);

    @Autowired
    private Scheduler scheduler;


    @Override
    public void addJob(String jobName, String jobGroupName, int jobTime, int runCount,String beanName,Object jobParam) throws Exception {
        logger.info(" 新增一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=" + jobTime + "," +
                "runCount=" + runCount);
        QuartzJobBean bean = SpringUtils.getApplicationContext().getBean(beanName,QuartzJobBean.class);
        Date date = JobUtils.addJob(scheduler, bean.getClass(), jobName, jobGroupName, jobTime, runCount,jobParam);
        logger.info(" job任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + " 执行完成 . " + date);
    }

    @Override
    public void addJob(String jobName, String jobGroupName, String cron,String beanName,Object jobParam) throws Exception {
        logger.info(" 新增一个任务 jobName=" + jobName + ",jobGroupName" + ",jobGroupName="+jobGroupName + ",jobTime=" + cron);
        QuartzJobBean bean = SpringUtils.getApplicationContext().getBean(beanName,QuartzJobBean.class);
        Date date = JobUtils.addJob(scheduler, bean.getClass(), jobName, jobGroupName, cron,jobParam);
        logger.info(" job任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + " 执行完成 . " + date);
    }

    /**
     * 修改 一个job的 时间表达式
     *
     * @param jobName
     * @param jobGroupName
     * @param jobTime
     */
    @Override
    public void updateJob(String jobName, String beanName, String jobGroupName,String jobTime, Object jobParam) throws Exception {
        logger.info(" 修改一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=" + jobTime);
        QuartzJobBean bean = SpringUtils.getApplicationContext().getBean(beanName,QuartzJobBean.class);
        JobUtils.updateJob(scheduler, bean.getClass() ,jobName, jobGroupName, jobTime,jobParam);
        logger.info(" job任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + " 执行完成 . ");
    }

    /**
     * 删除任务一个job
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     */
    @Override
    public void deleteJob(String jobName, String jobGroupName) throws Exception {
        logger.info(" 删除一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=");
        boolean result = JobUtils.deleteJob(scheduler, jobName, jobGroupName);
        logger.info(" job任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + " 执行完成." + result);
    }
    /**
     * 暂停一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    @Override
    public void pauseJob(String jobName, String jobGroupName) throws Exception {
        logger.info(" 暂停一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=");
        JobUtils.pauseJob(scheduler, jobName, jobGroupName);
        logger.info(" job任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + " 执行完成.");
    }

    /**
     * 恢复一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    @Override
    public void resumeJob(String jobName, String jobGroupName) throws Exception {
        logger.info(" 恢复一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=");
        JobUtils.resumeJob(scheduler, jobName, jobGroupName);
        logger.info(" 恢复一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + "执行完成");
    }

    /**
     * 立即执行一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    @Override
    public void runAJobNow(String jobName, String jobGroupName) throws Exception {
        logger.info(" 立即执行一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + ",jobTime=");
        JobUtils.runAJobNow(scheduler, jobName, jobGroupName);
        logger.info(" 立即执行一个任务 jobName=" + jobName + ",jobGroupName" + jobGroupName + "完成 ...");

    }

    @Override
    public List<Map<String,Object>> getRunningJobList() throws Exception {
        return JobUtils.queryRunJob(scheduler);
    }

    @Override
    public List<Map<String,Object>> getAllJobList() throws Exception {
        return JobUtils.queryAllJob(scheduler);
    }
}

14.新建JobUtils 任务调度工具类

package com.tjetc.utils;
import com.mchange.v1.util.MapUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.*;

/**
*@descriprion: 调度任务工具类 
*@author: xujirong
*@date: 2022/9/4 11:32
*/
public class JobUtils {

    /**
     * 增加一个job
     *
     * @param jobClass     任务实现类
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     * @param jobTime      时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes     运行的次数 (<0:表示不限次数)
     */
    public static Date addJob(Scheduler scheduler, Class<? extends QuartzJobBean> jobClass, String jobName, String
            jobGroupName, int jobTime,
                              int jobTimes, Object jobParam) throws Exception {

        Trigger trigger = null;
        JobDataMap jobDataMap =new JobDataMap();
        if(jobParam != null){
            jobDataMap.put("job_param",jobParam);
        }
        // 任务名称和组构成任务key
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).setJobData(jobDataMap)
                .build();
        // 使用simpleTrigger规则
        if (jobTimes < 0) {
            trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
                    .startNow().build();
        } else {
            trigger = TriggerBuilder
                    .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
                            .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
                    .startNow().build();
        }
        return scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     * 增加一个job
     * Trigger:触发器,Job:任务,Scheduler:调度器
     * @param jobClass     任务实现类
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     * @param cron      时间表达式 (如:0/5 * * * * ? )
     */
    public static Date addJob(Scheduler scheduler, Class<? extends QuartzJobBean> jobClass, String jobName, String
            jobGroupName, String cron, Object jobParam) throws Exception {
        // 创建jobDetail实例,绑定Job实现类
        // 指明job的名称,所在组的名称,以及绑定job类
        // 任务名称和组构成任务key
        JobDataMap jobDataMap =new JobDataMap();
        if(jobParam != null){
            jobDataMap.put("job_param",jobParam);
        }
        // JobBuilder.newJob(jobClass)构建任务-指向绑定任务的类
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).setJobData(jobDataMap).build();
        // 定义调度触发规则
        // 使用cornTrigger规则
        // 触发器key
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                .withSchedule(CronScheduleBuilder.cronSchedule(cron)).startNow().build();
        // 把作业和触发器注册到任务调度中
        return scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     * 修改 一个job的 时间表达式
     *
     * @param jobName
     * @param jobGroupName
     * @param jobTime
     */
    public static Date updateJob(Scheduler scheduler, Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Object jobParam) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        JobDataMap jobDataMap =new JobDataMap();
        if(jobParam != null){
            jobDataMap.put("job_param",jobParam);
        }
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();

        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).setJobData(jobDataMap)
                .build();

        deleteJob( scheduler,  jobName,  jobGroupName); //首先删除旧作业
        scheduler.scheduleJob(jobDetail, trigger); //注册新作业到任务调度中
        return scheduler.rescheduleJob(triggerKey, trigger); //重启触发器,更新触发参数
    }

    /**
     * 删除任务一个job
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     */

    public static boolean deleteJob(Scheduler scheduler, String jobName, String jobGroupName) throws SchedulerException {
        return scheduler.deleteJob(new JobKey(jobName, jobGroupName));
    }

    /**
     * 暂停一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public static void pauseJob(Scheduler scheduler, String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public static void resumeJob(Scheduler scheduler, String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
        scheduler.resumeJob(jobKey);
    }

    /**
     * 立即执行一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public static void runAJobNow(Scheduler scheduler, String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
        scheduler.triggerJob(jobKey);
    }

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     */
    public static List<Map<String, Object>> queryAllJob(Scheduler scheduler) {
        List<Map<String, Object>> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            jobList = new ArrayList<Map<String, Object>>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                JobDataMap jobDataMap = scheduler.getJobDetail(jobKey).getJobDataMap();
                for (Trigger trigger : triggers) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description", "触发器:" + trigger.getKey());
                    //Object jobParam = MapUtils.getObject(jobDataMap,"job_param");
                    //map.put("job_param",jobParam);
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression);
                    }
                    jobList.add(map);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }

    /**
     * 获取所有正在运行的job
     *
     * @return
     */
    public static List<Map<String, Object>> queryRunJob(Scheduler scheduler) {
        List<Map<String, Object>> jobList = null;
        try {
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                Map<String, Object> map = new HashMap<String, Object>();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                map.put("jobName", jobKey.getName());
                map.put("jobGroupName", jobKey.getGroup());
                map.put("description", "触发器:" + trigger.getKey());
                JobDataMap jobDataMap = trigger.getJobDataMap();
                //Object jobParam = MapUtils.getObject(jobDataMap,"job_param");
                //map.put("job_param",jobParam);
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                map.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    map.put("jobTime", cronExpression);
                }
                jobList.add(map);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }
}

15.新建SchedulerJobBean->定时任务定义

/**
 * @belongProject:hibernate
 * @belongPackage:com.tjetc.scheduler.test
 * @author:xujirong
 * @dscription:定时任务表-调度测试
 * @date:2022-09-03 15:13
 * @version:1.0
 */
@Component(value = "SchedulerJobBean")//给bean取一个名字
@CronJob(cron = "0/5 * * * * ? *",beanName = "SchedulerJobBean",chineseName = "定时任务测试",group = "test",node = "node5")
public class SchedulerJobBean extends QuartzJobBean {

    @Autowired
    private SchedulerJobMapper schedulerJobMapper;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

        List<Map<String, Object>> mapList = schedulerJobMapper.selectSchedulerJobAll();

        System.out.println("mapList = " + mapList);

    }
}

16.在springboot启动类中的相关注解

@SpringBootApplication
@EnableScheduling
@MapperScan("com.tjetc.mapper.**")
@ComponentScan("com.tjetc.scheduler.**")
@ComponentScan("com.tjetc.service.*")
public class SpringbootQuartzApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootQuartzApplication.class, args);
    }

}

相关文章:

  • python简介常考面试题目:python是什么,有什么好处,python2和python3的主要区别
  • SpringCloud Stream消息驱动
  • JVisualVM 中线程状态(运行/休眠/等待/驻留/监视)解析
  • 常识——绳结打折法
  • AVL树的特性和模拟实现
  • java剧院售票系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • SpringBoot-36-分布式理论概述
  • 第一章 Linux及Linux Shell简介
  • http客户端Feign
  • SpringBoot-37-RPC概述
  • tensorflo之keras高层接口
  • OpenCV图像处理学习二十一,直方图比较方法
  • 第5章 总体设计【软件设计一般分为总体设计和详细设计,它们之间的关系是全局与局部】
  • java开放式教学评价管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • define宏定义和const的区别
  • Angular数据绑定机制
  • in typeof instanceof ===这些运算符有什么作用
  • Javascript 原型链
  • JavaScript类型识别
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • node学习系列之简单文件上传
  • 记一次删除Git记录中的大文件的过程
  • 蓝海存储开关机注意事项总结
  • 前端
  • 如何在 Tornado 中实现 Middleware
  • 用mpvue开发微信小程序
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #includecmath
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (11)MATLAB PCA+SVM 人脸识别
  • (4) PIVOT 和 UPIVOT 的使用
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (转)c++ std::pair 与 std::make
  • (转)人的集合论——移山之道
  • (转)四层和七层负载均衡的区别
  • .htaccess配置常用技巧
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .net 验证控件和javaScript的冲突问题
  • @ComponentScan比较
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [2010-8-30]
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [HTML]Web前端开发技术28(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页
  • [Java][算法 双指针]Day 02---LeetCode 热题 100---04~07
  • [Linux]于Mac在配置Linuxserver安装Nginx+PHP
  • [linux学习]apt-get参数解析
  • [MFC] VS2013版本MFC工程移植到VC6.0上
  • [MZ test.16]P2 math 乘方e