• SpingBoot整合Quartz框架实现动态定时任务(支持实时增删改查任务)


    1.前言

    2. 关于Quartz入门讲解推荐

    3. 关于参考代码地址请进

    • 经朋友分享clone了下面地址的代码,发现里面刚好有介绍Quartz,本来一直都想弄个关于Quartz的demo,一直没弄,看完之后觉得有必要弄个demo演示一下,推荐大家clone大佬上传到gitHub上的代码,如果你不clone直接看我的demo也行,我下面的就是做了改动,初始化表也少了些
      https://github.com/xkcoding/spring-boot-demo.

    4. 先看效果

    • 新增任务
      在这里插入图片描述
    • 查询、修改状态、删除等
      在这里插入图片描述

    5. 准备工作

    5.1 数据库

    • ① 初始化下面几张表:qrtz,创表即可,没有数据,创表语句后面贴,本来11张表,我这里用到这几个,所以建全部表的话,可以参考上面github上的
      在这里插入图片描述
    • 在页面新增任务之后会自动填充这几张表的数据,当然你也可以数据库里直接insert,就是麻烦一点,先截图简单看一下这几个表的数据结构
      在这里插入图片描述
      在这里插入图片描述
    • dog_play_plan 这个表是根据业务逻辑自己创建,后面介绍

    5.2 Java后端配置等

    5.2.1 pom 文件

    • 如下:
      在这里插入图片描述
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-quartz</artifactId>
       </dependency>
      
      • 1
      • 2
      • 3
      • 4

    5.2.2 yml 配置文件

    • 如下:
      在这里插入图片描述
      spring:
        quartz:
          # 参见 org.springframework.boot.autoconfigure.quartz.QuartzProperties
          job-store-type: jdbc
          wait-for-jobs-to-complete-on-shutdown: true
          scheduler-name: SpringBootDemoScheduler
          properties:
            org.quartz.threadPool.threadCount: 5
            org.quartz.threadPool.threadPriority: 5
            org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
            org.quartz.jobStore.misfireThreshold: 5000
            org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
            org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            # 在调度流程的第一步,也就是拉取待即将触发的triggers时,是上锁的状态,即不会同时存在多个线程拉取到相同的trigger的情况,也就避免的重复调度的危险。参考:https://segmentfault.com/a/1190000015492260
            org.quartz.jobStore.acquireTriggersWithinLock: true
      #      org.quartz.jobStore.tablePrefix: sys_
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    6. 核心代码(直接粘代码的往下)

    6.1 vo、mapper 与 mapper.xml

    • 如图:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    6.2 controller、service

    • 先截一个新增,其他的下面贴代码
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    6.3 JobUtil.java

    • 如图:
      在这里插入图片描述

    6.4 BaseJob、定时 job(HelloJob为例)

    • 如图:
      在这里插入图片描述
      在这里插入图片描述

    6.5 job.html

    • 如图:
      在这里插入图片描述

    6.6 测试看效果

    • ① 启动服务,新增任务,查看新增的任务
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • ② 停用任务
      在这里插入图片描述
      在这里插入图片描述
      如果再启用,点恢复即可,傻瓜操作不介绍了,主要还是代码实现

    7. 实现一个业务场景

    7.1 dog_play_plan——计划表

    • 只说一下表就行了,实体和mapper和xml略了
      在这里插入图片描述
      在这里插入图片描述

    7.2 DogPlayPlanJob.java

    • 如下:
      在这里插入图片描述
      当然你也可以直接处理业务,不弄计划表,看自己情况,为啥弄个计划表,打个比方要发短信,SendMessageJob有一个,但是有的2分钟发一次有的5分钟发一次,所以你可以弄成同一个组sendMessage但是不同的任务名2分钟一次5分钟一次,但是你需要处理一下哪些业务数据是2分钟一次,哪些要5分钟一次,当然我这计划表可能不是更合理的,所以需要根据自己需要优化

    7.3 测试

    • 启动服务,添加业务,测试如下:
      在这里插入图片描述
      在这里插入图片描述

    7.3 后期可优化点

    1. 控制添加任务的数据

    • 新增任务不能随意,所以可以将业务名称、全类名维护字典或枚举或者直接将表单数据维护到一张表里,勾选数据进行反显,确保数据的正确性,尤其是全类名或cron表达式

    2. dog_play_plan 表

    • 这个表根据自己需求情况进行优化,我这里只是简单打个比方

    3. 定时任务管理应做成权限控制

    • 这个功能相对来说还是比较重要的,可以页面控制,但是要弄成权限控制,不能随意增删改查
    • 好了,简单说这么多,自己看着优化即可

    7.4 对上面7.3提的进行一个简单的优化

    1. 用枚举维护jobGroupName 和 jobName

    • 为了避免新增任务时数据乱写,所以维护起来
      在这里插入图片描述

    2. 新增 sys_job_manager 表——用来管理定时任务新增用

    • 表结构如下:
      在这里插入图片描述
      在这里插入图片描述
    • 用途
      此表后台可以开发者维护,页面新增任务的时候,取此表维护的数据,如果没有维护不允许乱新增任务

    3. 控制添加任务的查询sql

    • 查询所有可添加的任务:
      在这里插入图片描述
    • 检查添加的任务是否维护
      在这里插入图片描述

    4. controller修改如下

    • 如下
      在这里插入图片描述

    5. 新增时,注意数据

    • 如下:
      在这里插入图片描述

    6. 别忘了 dog_play_plan

    • 这个表看情况,没有对应的计划也可不维护,但是要先维护上面的任务,再新增这个计划
      在这里插入图片描述
      这个表,看自己需求情况进行优化,大概意思是这个意思

    8.附代码

    8.1 数据库建表

    • 按顺序如下:
      CREATE TABLE `qrtz_cron_triggers` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `TRIGGER_NAME` varchar(200) NOT NULL,
        `TRIGGER_GROUP` varchar(200) NOT NULL,
        `CRON_EXPRESSION` varchar(200) NOT NULL,
        `TIME_ZONE_ID` varchar(80) DEFAULT NULL,
        PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) USING BTREE
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      CREATE TABLE `qrtz_fired_triggers` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `ENTRY_ID` varchar(95) NOT NULL,
        `TRIGGER_NAME` varchar(200) NOT NULL,
        `TRIGGER_GROUP` varchar(200) NOT NULL,
        `INSTANCE_NAME` varchar(200) NOT NULL,
        `FIRED_TIME` bigint(20) NOT NULL,
        `SCHED_TIME` bigint(20) NOT NULL,
        `PRIORITY` int(11) NOT NULL,
        `STATE` varchar(16) NOT NULL,
        `JOB_NAME` varchar(200) DEFAULT NULL,
        `JOB_GROUP` varchar(200) DEFAULT NULL,
        `IS_NONCONCURRENT` bit(1) DEFAULT NULL,
        `REQUESTS_RECOVERY` bit(1) DEFAULT NULL,
        PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      CREATE TABLE `qrtz_job_details` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `JOB_NAME` varchar(200) NOT NULL,
        `JOB_GROUP` varchar(200) NOT NULL,
        `DESCRIPTION` varchar(250) DEFAULT NULL,
        `JOB_CLASS_NAME` varchar(250) NOT NULL,
        `IS_DURABLE` bit(1) NOT NULL,
        `IS_NONCONCURRENT` bit(1) NOT NULL,
        `IS_UPDATE_DATA` bit(1) NOT NULL,
        `REQUESTS_RECOVERY` bit(1) NOT NULL,
        `JOB_DATA` blob,
        PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      CREATE TABLE `qrtz_locks` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `LOCK_NAME` varchar(40) NOT NULL,
        PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      
      CREATE TABLE `qrtz_paused_trigger_grps` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `TRIGGER_GROUP` varchar(200) NOT NULL,
        PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='不加启动报错';
      
      CREATE TABLE `qrtz_triggers` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `TRIGGER_NAME` varchar(200) NOT NULL,
        `TRIGGER_GROUP` varchar(200) NOT NULL,
        `JOB_NAME` varchar(200) NOT NULL,
        `JOB_GROUP` varchar(200) NOT NULL,
        `DESCRIPTION` varchar(250) DEFAULT NULL,
        `NEXT_FIRE_TIME` bigint(20) DEFAULT NULL,
        `PREV_FIRE_TIME` bigint(20) DEFAULT NULL,
        `PRIORITY` int(11) DEFAULT NULL,
        `TRIGGER_STATE` varchar(16) NOT NULL,
        `TRIGGER_TYPE` varchar(8) NOT NULL,
        `START_TIME` bigint(20) NOT NULL,
        `END_TIME` bigint(20) DEFAULT NULL,
        `CALENDAR_NAME` varchar(200) DEFAULT NULL,
        `MISFIRE_INSTR` smallint(6) DEFAULT NULL,
        `JOB_DATA` blob,
        PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      CREATE TABLE `qrtz_simple_triggers` (
        `SCHED_NAME` varchar(120) NOT NULL,
        `TRIGGER_NAME` varchar(200) NOT NULL,
        `TRIGGER_GROUP` varchar(200) NOT NULL,
        `REPEAT_COUNT` bigint(20) NOT NULL,
        `REPEAT_INTERVAL` bigint(20) NOT NULL,
        `TIMES_TRIGGERED` bigint(20) NOT NULL,
        PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
        CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='修改定时任务时用这个';
      
      • 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

    8.2 Java核心代码

    1. vo、mapper 与 mapper.xml 等

    • ① JobForm.java
      package com.liu.susu.task.quartz.vobo.form;
      
      import lombok.Data;
      import lombok.experimental.Accessors;
      
      import javax.validation.constraints.NotBlank;
      
      @Data
      @Accessors(chain = true)
      public class JobForm {
          /**
           * 定时任务名
           */
          @NotBlank(message = "任务名称")
          private String jobName;
      
          /**
           * 任务组名
           */
          @NotBlank(message = "任务组名不能为空")
          private String jobGroupName;
      
          /**
           * 定时任务全类名
           */
          @NotBlank(message = "定时任务全类名")
          private String jobClassName;
      
          /**
           * 定时任务cron表达式
           */
          @NotBlank(message = "cron表达式不能为空")
          private String cronExpression;
      }
      
      
      • 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
    • ② JobAndTriggerVo.java
      package com.liu.susu.task.quartz.vobo.vo;
      
      import lombok.Data;
      
      import java.math.BigInteger;
      
      @Data
      public class JobAndTriggerVo {
          /**
           * 定时任务名称
           */
          private String jobName;
          /**
           * 定时任务组
           */
          private String jobGroup;
          /**
           * 定时任务全类名
           */
          private String jobClassName;
          /**
           * 触发器名称
           */
          private String triggerName;
          /**
           * 触发器组
           */
          private String triggerGroup;
          /**
           * 重复间隔
           */
          private BigInteger repeatInterval;
          /**
           * 触发次数
           */
          private BigInteger timesTriggered;
          /**
           * cron 表达式
           */
          private String cronExpression;
          /**
           * 时区
           */
          private String timeZoneId;
          /**
           * 定时任务状态
           */
          private String triggerState;
      }
      
      
      • 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
    • ③ JobMapper.java
      package com.liu.susu.mapper.task;
      
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      import org.apache.ibatis.annotations.Mapper;
      import org.springframework.stereotype.Repository;
      
      import java.util.List;
      
      @Mapper
      @Repository
      public interface JobMapper {
      
          /**
           * 查询定时作业和触发器列表
           */
          List<JobAndTriggerVo> list();
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • ④ JobMapper.xml
      
      DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.liu.susu.mapper.task.JobMapper">
      
        <select id="list" resultType="com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo">
      	SELECT
      		job_details.`JOB_NAME`,
      		job_details.`JOB_GROUP`,
      		job_details.`JOB_CLASS_NAME`,
      		cron_triggers.`CRON_EXPRESSION`,
      		cron_triggers.`TIME_ZONE_ID`,
      		qrtz_triggers.`TRIGGER_NAME`,
      		qrtz_triggers.`TRIGGER_GROUP`,
      		qrtz_triggers.`TRIGGER_STATE`
      	FROM
      		`QRTZ_JOB_DETAILS` job_details
      		LEFT JOIN `QRTZ_CRON_TRIGGERS` cron_triggers ON job_details.`JOB_NAME` = cron_triggers.`TRIGGER_NAME`
      		AND job_details.`JOB_GROUP` = cron_triggers.`TRIGGER_GROUP`
      		LEFT JOIN `QRTZ_TRIGGERS` qrtz_triggers ON qrtz_triggers.`TRIGGER_NAME` = job_details.`JOB_NAME`
      		AND qrtz_triggers.`TRIGGER_GROUP` = job_details.`JOB_GROUP`
          select>
      mapper>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

    2. controller、service

    • ① JobController.java
      package com.liu.susu.controller.task;
      
      import cn.hutool.core.util.ObjectUtil;
      import cn.hutool.core.util.StrUtil;
      import com.github.pagehelper.PageInfo;
      import com.liu.susu.common.ResultData;
      import com.liu.susu.common.ReturnCode;
      import com.liu.susu.service.task.JobService;
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      import com.liu.susu.task.quartz.vobo.form.JobForm;
      import lombok.extern.slf4j.Slf4j;
      import org.quartz.SchedulerException;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.*;
      
      import javax.validation.Valid;
      
      
      @RestController
      @RequestMapping("/job")
      @Slf4j
      public class JobController {
          private final JobService jobService;
      
          @Autowired
          public JobController(JobService jobService) {
              this.jobService = jobService;
          }
      
          /**
           * 保存定时任务
           */
          @PostMapping
          public ResultData addJob(@Valid JobForm form) {
              try {
                  jobService.addJob(form);
                  return new ResultData(ReturnCode.INSERT_SUCCESS);
              } catch (Exception e) {
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
          /**
           * 暂停定时任务
           */
          @PutMapping(params = "pause")
          public ResultData pauseJob(JobForm form) throws SchedulerException {
              if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) {
                  return new ResultData(ReturnCode.FAIL_NO_PARAM, "参数不能为空!");
              }
              jobService.pauseJob(form);
              return new ResultData(ReturnCode.SUCCESS_000000, "暂停成功!");
          }
      
          /**
           * 恢复定时任务
           */
          @PutMapping(params = "resume")
          public ResultData resumeJob(JobForm form) throws SchedulerException {
              if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) {
                  return new ResultData(ReturnCode.FAIL_NO_PARAM, "参数不能为空!");
              }
              jobService.resumeJob(form);
              return new ResultData(ReturnCode.SUCCESS_000000, "恢复成功!");
          }
      
          /**
           * 修改定时任务,定时时间
           */
          @PutMapping(params = "cron")
          public ResultData cronJob(@Valid JobForm form) {
              try {
                  jobService.cronJob(form);
                  return new ResultData(ReturnCode.UPDATE_SUCCESS, "修改成功!");
              } catch (Exception e) {
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
          /**
           * 删除定时任务
           */
          @DeleteMapping
          public ResultData deleteJob(JobForm form) throws SchedulerException {
              if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) {
                  return new ResultData(ReturnCode.FAIL_NO_PARAM, "参数不能为空!");
              }
              jobService.deleteJob(form);
              return new ResultData(ReturnCode.DELETE_SUCCESS, "删除成功!");
          }
      
          /**
           * 查询定时任务列表
           * @param currentPage
           * @param pageSize
           * @return
           */
          @RequestMapping
          public ResultData jobList(Integer currentPage, Integer pageSize) {
              if (ObjectUtil.isNull(currentPage)) {
                  currentPage = 1;
              }
              if (ObjectUtil.isNull(pageSize)) {
                  pageSize = 10;
              }
              PageInfo<JobAndTriggerVo> all = jobService.list(currentPage, pageSize);
              return new ResultData(ReturnCode.SELECT_SUCCESS, all);
          }
      
      }
      
      • 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
    • ② JobService.java
      package com.liu.susu.service.task;
      
      import com.github.pagehelper.PageInfo;
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      import com.liu.susu.task.quartz.vobo.form.JobForm;
      import org.quartz.SchedulerException;
      
      public interface JobService {
          /**
           * 添加并启动定时任务
           */
          void addJob(JobForm form) throws Exception;
      
          /**
           * 删除定时任务
           */
          void deleteJob(JobForm form) throws SchedulerException;
      
          /**
           * 暂停定时任务
           */
          void pauseJob(JobForm form) throws SchedulerException;
      
          /**
           * 恢复定时任务
           */
          void resumeJob(JobForm form) throws SchedulerException;
      
          /**
           * 重新配置定时任务
           */
          void cronJob(JobForm form) throws Exception;
      
          /**
           * 查询定时任务列表
           */
          PageInfo<JobAndTriggerVo> list(Integer currentPage, Integer pageSize);
      }
      
      
      • 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
    • ③ JobServiceImpl.java
      package com.liu.susu.service.task.impl;
      
      import com.github.pagehelper.PageHelper;
      import com.github.pagehelper.PageInfo;
      import com.liu.susu.mapper.task.JobMapper;
      import com.liu.susu.service.task.JobService;
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      import com.liu.susu.task.quartz.vobo.form.JobForm;
      import com.liu.susu.utils.JobUtil;
      import lombok.extern.slf4j.Slf4j;
      import org.quartz.*;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import java.util.List;
      
      
      @Service
      @Slf4j
      public class JobServiceImpl implements JobService {
          private final Scheduler scheduler;
          private final JobMapper jobMapper;
      
          @Autowired
          public JobServiceImpl(Scheduler scheduler, JobMapper jobMapper) {
              this.scheduler = scheduler;
              this.jobMapper = jobMapper;
          }
      
          /**
           * 添加并启动定时任务
           */
          @Override
          public void addJob(JobForm form) throws Exception {
              // 启动调度器
              scheduler.start();
      
              // 构建Job信息
      //        JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobClassName(), form.getJobGroupName()).build();
              JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobName(), form.getJobGroupName()).build();
      
              // Cron表达式调度构建器(即任务执行的时间)
              CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getCronExpression());
      
              //根据Cron表达式构建一个Trigger
      //        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobClassName(), form.getJobGroupName()).withSchedule(cron).build();
              CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobName(), form.getJobGroupName()).withSchedule(cron).build();
      
              try {
                  scheduler.scheduleJob(jobDetail, trigger);
              } catch (SchedulerException e) {
                  log.error("【定时任务】创建失败!", e);
                  throw new Exception("【定时任务】创建失败!");
              }
      
          }
      
          /**
           * 删除定时任务
           */
          @Override
          public void deleteJob(JobForm form) throws SchedulerException {
              scheduler.pauseTrigger(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
              scheduler.unscheduleJob(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
              scheduler.deleteJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
          }
      
          /**
           * 暂停定时任务
           */
          @Override
          public void pauseJob(JobForm form) throws SchedulerException {
              scheduler.pauseJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
          }
      
          /**
           * 恢复定时任务
           */
          @Override
          public void resumeJob(JobForm form) throws SchedulerException {
              scheduler.resumeJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
          }
      
          /**
           * 重新配置定时任务
           */
          @Override
          public void cronJob(JobForm form) throws Exception {
              try {
                  TriggerKey triggerKey = TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName());
                  // 表达式调度构建器
                  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(form.getCronExpression());
      
                  CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
      
                  // 根据Cron表达式构建一个Trigger
                  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
      
                  // 按新的trigger重新设置job执行
                  scheduler.rescheduleJob(triggerKey, trigger);
              } catch (SchedulerException e) {
                  log.error("【定时任务】更新失败!", e);
                  throw new Exception("【定时任务】创建失败!");
              }
          }
      
          /**
           * 查询定时任务列表
           */
          @Override
          public PageInfo<JobAndTriggerVo> list(Integer currentPage, Integer pageSize) {
              PageHelper.startPage(currentPage, pageSize);
              List<JobAndTriggerVo> list = jobMapper.list();
              return new PageInfo<>(list);
          }
      }
      
      
      • 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

    3. JobUtil.java

    • 如下:
      package com.liu.susu.utils;
      
      
      import com.liu.susu.task.quartz.job.base.BaseJob;
      
      /**
       * 定时任务反射工具类
       */
      public class JobUtil {
          /**
           * 根据全类名获取Job实例
           */
          public static BaseJob getClass(String classname) throws Exception {
              Class<?> clazz = Class.forName(classname);
              return (BaseJob) clazz.newInstance();
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

    4. BaseJob、HelloJob

    • ① BaseJob.java
      package com.liu.susu.task.quartz.job.base;
      
      import org.quartz.*;
      
      
      public interface BaseJob extends Job {
      
          @Override
          void execute(JobExecutionContext context) throws JobExecutionException;
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • ② HelloJob.java
      package com.liu.susu.task.quartz.job;
      
      import com.liu.susu.task.quartz.job.base.BaseJob;
      import lombok.extern.slf4j.Slf4j;
      import org.quartz.JobExecutionContext;
      import org.quartz.JobKey;
      
      import java.time.LocalDateTime;
      
      @Slf4j
      public class HelloJob implements BaseJob {
      
          @Override
          public void execute(JobExecutionContext context) {
      
              JobKey key = context.getJobDetail().getKey();
              if ("bb".equals(key.getName())){
                  log.info("处理bb定时任务的业务…… 执行时间-->: {}", LocalDateTime.now());
              }
              if ("aa".equals(key.getName())){
                  log.info("处理aa定时任务的业务…… 执行时间-->: {}",LocalDateTime.now());
              }
              log.info("处理aa、bb外的定时任务,执行时间-->: {}",LocalDateTime.now());
      
          }
      
      }
      
      
      • 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

    5. job.html

    • 如下:
      DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title>spring-boot-demo-task-quartztitle>
          <link href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.9/theme-chalk/index.css" rel="stylesheet">
          <script src="https://cdn.bootcss.com/vue/2.5.17/vue.min.js">script>
          <script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js">script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.9/index.js">script>
      
          <style>
              #top {
                  /*background: #20A0FF;*/
                  padding: 5px;
                  /*overflow: hidden*/
              }
          style>
      
      head>
      <body>
      <div id="job">
          <div id="top">
              <el-button size="small" type="primary" plain @click="search" :loading="loading" icon="el-icon-search">查询
              el-button>
              <el-button size="small" type="primary" plain @click="handleadd" icon="el-icon-plus">添加el-button>
          div>
          <br/>
          <div>
              <el-table ref="jobTable" :data="tableData" style="width:100%" border center>
                  <el-table-column prop="jobName" label="任务名称" show-overflow-tooltip align="center">el-table-column>
                  <el-table-column prop="jobGroup" label="任务所在组" sortable align="center">el-table-column>
                  <el-table-column prop="jobClassName" label="任务类名" align="center">el-table-column>
                  <el-table-column prop="triggerName" label="触发器名称" align="center">el-table-column>
                  <el-table-column prop="triggerGroup" label="触发器所在组" sortable align="center">el-table-column>
                  <el-table-column prop="cronExpression" label="表达式" align="center">el-table-column>
                  <el-table-column prop="timeZoneId" label="时区" align="center">el-table-column>
                  <el-table-column prop="triggerState" label="状态" align="center" :formatter="formatState">el-table-column>
                  <el-table-column label="操作" width="300" align="center">
                      <template scope="scope">
                          <el-button size="small" type="warning" @click="handlePause(scope.$index, scope.row)">
                              暂停
                          el-button>
                          <el-button size="small" type="info" @click="handleResume(scope.$index, scope.row)">
                              恢复
                          el-button>
                          <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)">
                              删除
                          el-button>
                          <el-button size="small" type="success" @click="handleUpdate(scope.$index, scope.row)">
                              修改
                          el-button>
                      template>
                  el-table-column>
              el-table>
      
              <div align="center">
                  <el-pagination
                          @size-change="handleSizeChange"
                          @current-change="handleCurrentChange"
                          :current-page="currentPage"
                          :page-sizes="[10, 20, 30, 40]"
                          :page-size="pagesize"
                          layout="total, sizes, prev, pager, next, jumper"
                          :total="totalCount">
                  el-pagination>
              div>
          div>
      
          <el-dialog title="添加任务" :visible.sync="dialogFormVisible">
              <el-form :model="form">
                  <el-form-item label="任务名称" label-width="100px" style="width:90%">
                      <el-input v-model="form.jobName" auto-complete="off">el-input>
                  el-form-item>
                <el-form-item label="任务类名称" label-width="100px" style="width:90%">
                  <el-input v-model="form.jobClassName" auto-complete="off">el-input>
                el-form-item>
                  <el-form-item label="任务分组" label-width="100px" style="width:90%">
                      <el-input v-model="form.jobGroup" auto-complete="off">el-input>
                  el-form-item>
                  <el-form-item label="表达式" label-width="100px" style="width:90%">
                      <el-input v-model="form.cronExpression" auto-complete="off">el-input>
                  el-form-item>
              el-form>
              <div slot="footer" class="dialog-footer">
                  <el-button @click="dialogFormVisible = false">取 消el-button>
                  <el-button type="primary" @click="add">确 定el-button>
              div>
          el-dialog>
      
          <el-dialog title="修改任务" :visible.sync="updateFormVisible">
              <el-form :model="updateform">
                  <el-form-item label="表达式" label-width="100px" style="width:90%">
                      <el-input v-model="updateform.cronExpression" auto-complete="off">el-input>
                  el-form-item>
              el-form>
              <div slot="footer" class="dialog-footer">
                  <el-button @click="updateFormVisible = false">取 消el-button>
                  <el-button type="primary" @click="update">确 定el-button>
              div>
          el-dialog>
      div>
      
      <footer align="center">
          <p>© Quartz 定时任务管理p>
      footer>
      
      <script>
          var vue = new Vue({
              el: "#job",
              data: {
                  //表格当前页数据
                  tableData: [],
                  //请求的URL
                  url: 'job',
                  //默认每页数据量
                  pagesize: 10,
                  //当前页码
                  currentPage: 1,
                  //查询的页码
                  start: 1,
                  //默认数据总数
                  totalCount: 1000,
                  //添加对话框默认可见性
                  dialogFormVisible: false,
                  //修改对话框默认可见性
                  updateFormVisible: false,
                  //提交的表单
                  form: {
                      jobName: '',
                      jobGroup: '',
                      cronExpression: ''
                  },
                  updateform: {
                      jobName: '',
                      jobGroup: '',
                      cronExpression: ''
                  },
                  loading: false
              },
              methods: {
                  // 格式化状态
                  formatState: function (row, column, cellValue, index) {
                      if (row.triggerState === 'WAITING' || row.triggerState === 'ACQUIRED') {
                          return "运行中";
                      } else if (row.triggerState === 'PAUSED') {
                          return "暂停";
                      } else {
                          return "未知状态";
                      }
                  },
                  // 从服务器读取数据
                  loadData: function (currentPage, pageSize) {
                      this.loading = true;
                      this.$http.get('job?' + 'currentPage=' + currentPage + '&pageSize=' + pageSize).then(function (res) {
                          console.log(res);
                          this.tableData = res.body.data.list;
                          this.totalCount = res.body.data.total;
                          this.loading = false;
                      }, function () {
                          console.log('failed');
                      });
                  },
                  // 删除任务
                  handleDelete: function (index, row) {
                      this.$http.delete('job', {
                          params: {
                              "jobClassName": row.jobName,
                              "jobGroupName": row.jobGroup
                          }
                      }, {emulateJSON: true}).then(function (res) {
                          this.loadData(this.currentPage, this.pagesize);
                      }, function () {
                          console.log('failed');
                      });
                  },
                  // 暂停任务
                  handlePause: function (index, row) {
                      this.$http.put('job?pause', {
                          "jobClassName": row.jobName,
                          "jobGroupName": row.jobGroup
                      }, {emulateJSON: true}).then(function (res) {
                          this.loadData(this.currentPage, this.pagesize);
                      }, function () {
                          console.log('failed');
                      });
                  },
                  // 恢复任务
                  handleResume: function (index, row) {
                      this.$http.put('job?resume', {
                          "jobClassName": row.jobName,
                          "jobGroupName": row.jobGroup
                      }, {emulateJSON: true}).then(function (res) {
                          this.loadData(this.currentPage, this.pagesize);
                      }, function () {
                          console.log('failed');
                      });
                  },
                  // 搜索
                  search: function () {
                      this.loadData(this.currentPage, this.pagesize);
                  },
                  // 弹出对话框
                  handleadd: function () {
                      this.dialogFormVisible = true;
                  },
                  // 添加
                  add: function () {
                      this.$http.post('job', {
                          "jobName": this.form.jobName,
                          "jobClassName": this.form.jobClassName,
                          "jobGroupName": this.form.jobGroup,
                          "cronExpression": this.form.cronExpression
                      }, {emulateJSON: true}).then(function (res) {
                          this.loadData(this.currentPage, this.pagesize);
                          this.dialogFormVisible = false;
                      }, function () {
                          console.log('failed');
                      });
                  },
                  // 更新
                  handleUpdate: function (index, row) {
                      console.log(row);
                      this.updateFormVisible = true;
                      this.updateform.jobName = row.jobName;
                      this.updateform.jobGroup = row.jobGroup;
                  },
                  // 更新任务
                  update: function () {
                      this.$http.put('job?cron',
                          {
                              "jobClassName": this.updateform.jobName,
                              "jobGroupName": this.updateform.jobGroup,
                              "cronExpression": this.updateform.cronExpression
                          }, {emulateJSON: true}
                      ).then(function (res) {
                          this.loadData(this.currentPage, this.pagesize);
                          this.updateFormVisible = false;
                      }, function () {
                          console.log('failed');
                      });
      
                  },
                  // 每页显示数据量变更
                  handleSizeChange: function (val) {
                      this.pagesize = val;
                      this.loadData(this.currentPage, this.pagesize);
                  },
                  // 页码变更
                  handleCurrentChange: function (val) {
                      this.currentPage = val;
                      this.loadData(this.currentPage, this.pagesize);
                  }
              }
          });
      
          //载入数据
          vue.loadData(vue.currentPage, vue.pagesize);
      script>
      
      body>
      html>
      
      • 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
      • 222
      • 223
      • 224
      • 225
      • 226
      • 227
      • 228
      • 229
      • 230
      • 231
      • 232
      • 233
      • 234
      • 235
      • 236
      • 237
      • 238
      • 239
      • 240
      • 241
      • 242
      • 243
      • 244
      • 245
      • 246
      • 247
      • 248
      • 249
      • 250
      • 251
      • 252
      • 253
      • 254
      • 255
      • 256
      • 257
      • 258
      • 259
      • 260
      • 261

    8.3 对于 7.4 优化后的代码 和 下载地址

    8.3.1 优化后的代码

    1. JobService.java

    • 如下:
      package com.liu.susu.service.task;
      
      import com.liu.susu.common.ResultData;
      import com.liu.susu.pojo.entity.sys.SysJobManagerEntity;
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      
      import java.util.List;
      
      public interface JobService {
      
          /**
           * 查询定时任务列表
           */
          List<JobAndTriggerVo> selectAllJobList();
      
          /**
           * 添加并启动定时任务
           */
          void addJob(SysJobManagerEntity form) throws Exception;
      
          /**
           * 暂停定时任务
           */
          ResultData pauseJob(String jobNameKey, String jobGroupNameCode);
      
          /**
           * 恢复定时任务
           */
          ResultData resumeJob(String jobNameKey, String jobGroupNameCode) ;
      
          /**
           * 重新配置定时任务
           */
          ResultData updateJobCron(String jobNameKey, String jobGroupNameCode,String newCron) ;
      
          /**
           * 删除定时任务
           */
          ResultData deleteJob(String jobNameKey, String jobGroupNameCode);
      
      
      }
      
      
      • 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

    2. JobServiceImpl.java

    • 如下:
      package com.liu.susu.service.task.impl;
      
      import com.liu.susu.common.ResultData;
      import com.liu.susu.common.ReturnCode;
      import com.liu.susu.mapper.task.JobMapper;
      import com.liu.susu.pojo.entity.sys.SysJobManagerEntity;
      import com.liu.susu.service.task.JobService;
      import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo;
      import com.liu.susu.utils.JobUtil;
      import lombok.extern.slf4j.Slf4j;
      import org.quartz.*;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import java.util.List;
      
      
      @Service
      @Slf4j
      public class JobServiceImpl implements JobService {
      
          @Autowired
          private Scheduler scheduler;
      
          @Autowired
          private JobMapper jobMapper;
      
          /**
           * 查询定时任务列表
           */
          @Override
          public List<JobAndTriggerVo> selectAllJobList() {
              return jobMapper.list();
          }
      
      
          /**
           * 添加并启动定时任务
           */
          @Override
          public void addJob(SysJobManagerEntity form) throws Exception {
              // 启动调度器
              scheduler.start();
      
              // 构建Job信息
              JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass())
                      .withIdentity(form.getJobNameKey(), form.getJobGroupNameCode()).build();
      
              // Cron表达式调度构建器(即任务执行的时间)
              CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getJobCron());
      
              //根据Cron表达式构建一个Trigger
              CronTrigger trigger = TriggerBuilder.newTrigger()
                      .withIdentity(form.getJobNameKey(), form.getJobGroupNameCode())
                      .withSchedule(cron).build();
      
              try {
                  scheduler.scheduleJob(jobDetail, trigger);
              } catch (SchedulerException e) {
                  log.error("【定时任务】创建失败!", e);
                  throw new Exception("【定时任务】创建失败!");
              }
      
          }
      
          /**
           * 暂停定时任务
           */
          @Override
          public ResultData pauseJob(String jobNameKey, String jobGroupNameCode) {
              try {
                  scheduler.pauseJob(JobKey.jobKey(jobNameKey, jobGroupNameCode));
                  return new ResultData(ReturnCode.SUCCESS_000000,"暂停成功!");
              } catch (SchedulerException e) {
                  e.printStackTrace();
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
          /**
           * 恢复定时任务
           */
          @Override
          public ResultData resumeJob(String jobNameKey, String jobGroupNameCode) {
              try {
                  scheduler.resumeJob(JobKey.jobKey(jobNameKey, jobGroupNameCode));
                  return new ResultData(ReturnCode.SUCCESS_000000,"定时任务恢复成功!");
              } catch (SchedulerException e) {
                  e.printStackTrace();
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
          /**
           * 修改定时任务
           */
          @Override
          public ResultData updateJobCron(String jobNameKey, String jobGroupNameCode,String newCron) {
              try {
                  TriggerKey triggerKey = TriggerKey.triggerKey(jobNameKey, jobGroupNameCode);
                  // 表达式调度构建器
                  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(newCron);
      
                  CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
      
                  // 根据Cron表达式构建一个Trigger
                  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
      
                  // 按新的trigger重新设置job执行
                  scheduler.rescheduleJob(triggerKey, trigger);
                  return new ResultData(ReturnCode.UPDATE_SUCCESS,"定时任务修改成功!");
              } catch (SchedulerException e) {
                  log.error("【定时任务】更新失败!", e);
                  e.printStackTrace();
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
          /**
           * 删除定时任务
           */
          @Override
          public ResultData deleteJob(String jobNameKey, String jobGroupNameCode)  {
              try {
                  scheduler.pauseTrigger(TriggerKey.triggerKey(jobNameKey, jobGroupNameCode));
                  scheduler.unscheduleJob(TriggerKey.triggerKey(jobNameKey, jobGroupNameCode));
                  scheduler.deleteJob(JobKey.jobKey(jobNameKey, jobGroupNameCode));
                  return new ResultData(ReturnCode.DELETE_SUCCESS,"定时任务删除成功!");
              } catch (SchedulerException e) {
                  e.printStackTrace();
                  return new ResultData(ReturnCode.FAIL_999999);
              }
          }
      
      }
      
      
      • 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

    3.JobController2.java

    • 如下:
    package com.liu.susu.controller.task;
    
    import com.github.pagehelper.PageHelper;
    import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
    import com.github.xiaoymin.knife4j.annotations.ApiSupport;
    import com.liu.susu.common.PageParam;
    import com.liu.susu.common.ResultData;
    import com.liu.susu.common.ReturnCode;
    import com.liu.susu.mapper.task.SysJobManagerMapper;
    import com.liu.susu.pojo.entity.sys.SysJobManagerEntity;
    import com.liu.susu.service.task.JobService;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    import org.apache.ibatis.annotations.Param;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.Valid;
    
    @Controller
    @RequestMapping("/sys/quartz/task")
    @Api(tags = "系统管理-->定时任务管理")
    @ApiSupport(author = "乘风破浪",order = 3)
    @Slf4j
    public class JobController2 {
    
        @Autowired
        private JobService jobService;
    
        @Autowired
        private SysJobManagerMapper sysJobManagerMapper;
    
    
        @ApiOperationSupport(author = "乘风破浪",order = 1)
        @ApiOperation(value = "查询定时任务列表")
        @PostMapping("/selectAllJob")
        @ResponseBody
        public ResultData selectAllJob(@Valid PageParam pageParam) {
            if (pageParam!=null){
                PageHelper.startPage(pageParam.getPageNum(),pageParam.getPageSize());
            }
            return ResultData.getPageBaseResultData(pageParam,jobService.selectAllJobList());
        }
    
        @ApiOperationSupport(author = "乘风破浪",order = 2)
        @ApiOperation(value = "新增定时任务")
        @PostMapping("/addNewJob")
        @ResponseBody
        public ResultData addNewJob(@RequestBody SysJobManagerEntity form) {
            if (form!=null && StringUtils.isNotEmpty(form.getJobGroupNameCode())
            && StringUtils.isNotEmpty(form.getJobNameKey())){
                //添加任务之前,先校验是否在可添加的列表中有维护
                int count = sysJobManagerMapper.findSysJobManager(form.getJobGroupNameCode(), form.getJobNameKey());
                if (count>0){
                    try {
                        jobService.addJob(form);
                        return new ResultData(ReturnCode.INSERT_SUCCESS);
                    } catch (Exception e) {
                        return new ResultData(ReturnCode.FAIL_999999);
                    }
                }else {
                    return new ResultData(ReturnCode.FAIL_999998,"没有维护要新增的定时任务,请先找管理员维护!");
                }
            }
            return new ResultData(ReturnCode.FAIL_NO_PARAM, "表单参数为空,请检查参数");
        }
    
        @ApiOperationSupport(author = "乘风破浪",order = 3)
        @ApiOperation(value = "暂停任务")
        @GetMapping("/pauseJob")
        @ResponseBody
        public ResultData pauseJob(@RequestParam(value = "jobNameKey",required = true) String jobNameKey,
                                   @RequestParam(value = "jobGroupNameCode",required = true) String jobGroupNameCode){
    
            if (StringUtils.isEmpty(jobNameKey) || StringUtils.isEmpty(jobGroupNameCode)){
                return new ResultData(ReturnCode.FAIL_NO_PARAM, "参数不能为空!");
            }
            return jobService.pauseJob(jobNameKey,jobGroupNameCode);
        }
    
        @ApiOperationSupport(author = "乘风破浪",order = 4)
        @ApiOperation(value = "恢复定时任务")
        @GetMapping("/resumeJob")
        @ResponseBody
        public ResultData resumeJob(@RequestParam(value = "jobNameKey") String jobNameKey,
                                    @RequestParam(value = "jobGroupNameCode") String jobGroupNameCode) {
            if (StringUtils.isEmpty(jobNameKey) || StringUtils.isEmpty(jobGroupNameCode)){
                return new ResultData(ReturnCode.FAIL_NO_PARAM, "参数不能为空!");
            }
            return jobService.resumeJob(jobNameKey,jobGroupNameCode);
        }
    
        @ApiOperationSupport(author = "乘风破浪",order = 5)
        @ApiOperation(value = "修改定时任务,定时时间")
        @GetMapping("/updateJobCron")
        @ResponseBody
        public ResultData updateJobCron(@Param("jobNameKey") String jobNameKey,
                                        @Param("jobGroupNameCode") String jobGroupNameCode,
                                        @Param("cron") String newCron) {
            return jobService.updateJobCron(jobNameKey, jobGroupNameCode, newCron);
        }
    
        @ApiOperationSupport(author = "乘风破浪",order = 6)
        @ApiOperation(value = "删除定时任务")
        @GetMapping("/deleteJob")
        @ResponseBody
        public ResultData deleteJob(@Param("jobNameKey") String jobNameKey,
                                    @Param("jobGroupNameCode") String jobGroupNameCode) {
    
            jobService.deleteJob(jobNameKey,jobGroupNameCode);
            return new ResultData(ReturnCode.DELETE_SUCCESS, "删除成功!");
        }
    
    
    }
    
    
    • 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

    8.3.2 下载地址

    • 我把这个集成到自己项目里了,优化后的代码也在,代码太多,所以就贴上面部分代码了,其他的自己根据需要可自行下载:

      springboot_mybatis小项目.

  • 相关阅读:
    leetcode43 字符串相乘
    6月25日PMI认证考点防疫要求及考场安排
    Ajax--初识Ajax--接口和案例 - 图书管理
    xcode开发ios应用简介
    MQ - 09 RabbitMQ的架构设计与实现
    HOW - Lodash 使用指南和源码学习
    深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv 计算机竞赛
    【排序算法】快速排序
    LiveData 的使用和原理
    【RocketMQ 九】mqadmin命令
  • 原文地址:https://blog.csdn.net/suixinfeixiangfei/article/details/125998134