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


    无需配置,直接写死的使用

    import org.springframework.scheduling.annotation.Scheduled;
    
    @Slf4j
    @Component
    public class Test {
    
        @Autowired
        private StudentService studentService;
    
        @Scheduled(cron="0/5 * * * * ? ") //每5秒执行一次
        public void execute(){
    
            List<Student> students = studentService.findAll();
    
            log.info("cron run"+students);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    一.有关于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>
    
    • 1
    • 2
    • 3
    • 4

    或者

    <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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    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";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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);
    
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221

    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);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    NacosException: endpoint is blank错误
    SpringBoot中使用EMQX实现MQTT通讯
    磁场设备主要有哪些
    uniapp微信小程序video视频监听播放时间
    可能是入门高阶数学的好通道 —— 很直观易记,又很难判断的真假的数学命题们
    山东省首版次高端软件申报指导
    JS 运算符使用
    代码随想录训练营第59天|503.下一个更大元素II,42.接雨水
    Linux权限
    电子商务平台系统
  • 原文地址:https://blog.csdn.net/MyBlogHiHi/article/details/126686275