(Java企业 / 公司项目)如何使用分布式任务调度框架Quartz集成 和 SpringBoot自带的定时任务集成?

SpringBoot自带的定时任务

首先在你的微服务项目中创建一个新的模块,定时调度模块

 pom.xml里面关联公共模块common的依赖其他不需要改变

 然后启动类别删,启动项目是否报错,写一个简单的测试类访问路径是否成功

package com.jiawa.train.batch.controller;

import com.jiawa.train.batch.feign.BusinessFeign;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {


    @Resource
    BusinessFeign businessFeign;

    @GetMapping("/hello")
    public String hello() {
        return "Hello World! Batch!";
    }
}

创建一个包job 创建类 SpringBootTestJob.java

 package com.jiawa.train.batch.job;

 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;

 /**
  * 适合单体应用,不适合集群
  * 没法实时更改定时任务状态和策略
  */
 @Component
 @EnableScheduling // 开启定时任务
 public class SpringBootTestJob {

     @Scheduled(cron = "0/5 * * * * ?")//   每5秒执行一次 每5秒执行一次 cron 从左到右空格隔开:秒 分钟 小时 日期 月份 星期
     private void test() {
         // 增加分布式锁,解决集群问题
         System.out.println("SpringBootTestJob TEST");
     }
 }

多个定时任务就写多个@Scheduled, 定时任务的三要素也要知道:1. 执行的内容:功能逻辑 2. 执行的策略: cron表达式  3. 开关: 开启定时任务

SpringBoot自带的定时任务缺点:  无法实时更改任务状态,就是当我想把定时任务暂停一下今天的数据有问题,但是这个就无法进行暂停所以用专业的任务调度的框架。

SpringBoot自带的定时任务优点:  开发速度快适合小型的项目,两个注解就好了

分布式任务调度框架Quartz集成

首先导入依赖pom.xml。 这里没有版本是因为我的这个是子模块 版本由父模块控制

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

跟着思路来导入了依赖之后我们就开始声明我们的任务了, 创建一个配置类 quartzConfig   触发器就是调用前面声明的任务方法来定时

 package com.jiawa.train.batch.config;

 import com.jiawa.train.batch.job.TestJob;
 import org.quartz.*;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;

 @Configuration
 public class QuartzConfig {

     /**
      * 声明一个任务
      * @return
      */
     @Bean
     public JobDetail jobDetail() {
         return JobBuilder.newJob(TestJob.class)
                 .withIdentity("TestJob", "test")//  任务名称和组构成任务key
                 .storeDurably()
                 .build();
     }

     /**
      * 声明一个触发器,什么时候触发这个任务
      * @return
      */
     @Bean
     public Trigger trigger() {
         return TriggerBuilder.newTrigger()// 创建一个新的触发器
                 .forJob(jobDetail()) // 将任务detail作为触发器要触发的任务
                 .withIdentity("trigger", "trigger")    // 为触发器设置一个唯一标识,例如 "trigger" 和 "trigger"
                 .startNow()  // 立即触发任务,从当前时间开始
                 .withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ?"))  // 设置触发器的调度规则,使用 cron 格式的字符串,表示每隔 2 分钟触发一次任务
                 .build();
     }
 }

上面代码写了注释的,任务名称TestJob这里就创建一个任务来对应,实现的是Job是框架quartz里面的接口

@DisallowConcurrentExecution //  禁止并发执行

package com.jiawa.train.batch.job;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution //  禁止并发执行
public class TestJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("TestJob TEST开始");
        // try {
        //     Thread.sleep(3000);
        // } catch (InterruptedException e) {
        //     e.printStackTrace();
        // }
        System.out.println("TestJob TEST结束");
    }
}

 这就集成了框架的使用,springboot自带的定时任务也在使用。前面是简单的使用

在项目中集成框架

数据库配置quartz框架调度任务,官方提供的数据库MySQL,创建这几张表记得分库

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  JOB_NAME  VARCHAR(200) NOT NULL  comment 'job名称',
  JOB_GROUP VARCHAR(200) NOT NULL  comment 'job组',
  DESCRIPTION VARCHAR(250) NULL  comment '描述',
  JOB_CLASS_NAME   VARCHAR(250) NOT NULL  comment 'job类名',
  IS_DURABLE VARCHAR(1) NOT NULL  comment '是否持久化',
  IS_NONCONCURRENT VARCHAR(1) NOT NULL  comment '是否非同步',
  IS_UPDATE_DATA VARCHAR(1) NOT NULL  comment '是否更新数据',
  REQUESTS_RECOVERY VARCHAR(1) NOT NULL  comment '请求是否覆盖',
  JOB_DATA BLOB NULL  comment 'job数据',
  PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_NAME VARCHAR(200) NOT NULL comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  JOB_NAME  VARCHAR(200) NOT NULL  comment 'job名称',
  JOB_GROUP VARCHAR(200) NOT NULL  comment 'job组',
  DESCRIPTION VARCHAR(250) NULL  comment '描述',
  NEXT_FIRE_TIME BIGINT(13) NULL  comment '下一次触发时间',
  PREV_FIRE_TIME BIGINT(13) NULL  comment '前一次触发时间',
  PRIORITY INTEGER NULL  comment '等级',
  TRIGGER_STATE VARCHAR(16) NOT NULL  comment '触发状态',
  TRIGGER_TYPE VARCHAR(8) NOT NULL  comment '触发类型',
  START_TIME BIGINT(13) NOT NULL  comment '开始时间',
  END_TIME BIGINT(13) NULL  comment '结束时间',
  CALENDAR_NAME VARCHAR(200) NULL  comment '日程名称',
  MISFIRE_INSTR SMALLINT(2) NULL  comment '未触发实例',
  JOB_DATA BLOB NULL  comment 'job数据',
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
  REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  REPEAT_COUNT BIGINT(7) NOT NULL  comment '重复执行次数',
  REPEAT_INTERVAL BIGINT(12) NOT NULL  comment '重复执行间隔',
  TIMES_TRIGGERED BIGINT(10) NOT NULL  comment '已经触发次数',
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CRON_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  CRON_EXPRESSION VARCHAR(200) NOT NULL  comment 'cron表达式',
  TIME_ZONE_ID VARCHAR(80)  comment '时区',
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  STR_PROP_1 VARCHAR(512) NULL  comment '开始配置1',
  STR_PROP_2 VARCHAR(512) NULL  comment '开始配置2',
  STR_PROP_3 VARCHAR(512) NULL  comment '开始配置3',
  INT_PROP_1 INT NULL  comment 'int配置1',
  INT_PROP_2 INT NULL  comment 'int配置2',
  LONG_PROP_1 BIGINT NULL  comment 'long配置1',
  LONG_PROP_2 BIGINT NULL  comment 'long配置2',
  DEC_PROP_1 NUMERIC(13,4) NULL  comment '配置描述1',
  DEC_PROP_2 NUMERIC(13,4) NULL  comment '配置描述2',
  BOOL_PROP_1 VARCHAR(1) NULL  comment 'bool配置1',
  BOOL_PROP_2 VARCHAR(1) NULL  comment 'bool配置2',
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  BLOB_DATA BLOB NULL  comment '数据',
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CALENDARS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  CALENDAR_NAME  VARCHAR(200) NOT NULL comment '日程名称',
  CALENDAR BLOB NOT NULL  comment '日程数据',
  PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  TRIGGER_GROUP  VARCHAR(200) NOT NULL  comment '触发器组',
  PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  ENTRY_ID VARCHAR(95) NOT NULL  comment 'entryId',
  TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',
  TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',
  INSTANCE_NAME VARCHAR(200) NOT NULL  comment '实例名称',
  FIRED_TIME BIGINT(13) NOT NULL  comment '执行时间',
  SCHED_TIME BIGINT(13) NOT NULL  comment '定时任务时间',
  PRIORITY INTEGER NOT NULL  comment '等级',
  STATE VARCHAR(16) NOT NULL  comment '状态',
  JOB_NAME VARCHAR(200) NULL  comment 'job名称',
  JOB_GROUP VARCHAR(200) NULL  comment 'job组',
  IS_NONCONCURRENT VARCHAR(1) NULL  comment '是否异步',
  REQUESTS_RECOVERY VARCHAR(1) NULL  comment '是否请求覆盖',
  PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  INSTANCE_NAME VARCHAR(200) NOT NULL  comment '实例名称',
  LAST_CHECKIN_TIME BIGINT(13) NOT NULL  comment '最近检入时间',
  CHECKIN_INTERVAL BIGINT(13) NOT NULL  comment '检入间隔',
  PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(
  SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',
  LOCK_NAME  VARCHAR(40) NOT NULL  comment 'lock名称',
  PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);

创建两个固定的配置类,这两个类在任何项目中可以使用都是差不多的固定写法

MyJobFactory.java

package com.jiawa.train.batch.config;

import jakarta.annotation.Resource;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component;

@Component
public class MyJobFactory extends SpringBeanJobFactory {

    @Resource
    private AutowireCapableBeanFactory beanFactory;

    /**
     * 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。
     */
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        beanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

创建一个config工具类,根据数据库进行调度任务 连接数据库指定定时时间。调度器

package com.jiawa.train.batch.config;

import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
public class SchedulerConfig {

    @Resource
    private MyJobFactory myJobFactory;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("dataSource") DataSource dataSource) throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);// 连接数据库
        factory.setJobFactory(myJobFactory);// 指定前面创建的配置类
        factory.setStartupDelay(2); //  延迟2秒启动
        return factory;
    }
}

 接下来开始完成定时任务的接口,使得定时任务让接口来控制,首先创建请求数据request

package com.jiawa.train.batch.req;

public class CronJobReq {
    private String group; // 分组

    private String name;//   任务名称

    private String description;//  描述

    private String cronExpression;//  执行时间表达式

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("CronJobDto{");
        sb.append("cronExpression='").append(cronExpression).append('\'');
        sb.append(", group='").append(group).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", description='").append(description).append('\'');
        sb.append('}');
        return sb.toString();
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

设置响应数据类response,进行set和get

package com.jiawa.train.batch.resp;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;

import java.util.Date;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class CronJobResp {
    private String group;// 分组

    private String name; // 任务名称

    private String description; // 描述

    private String state;// 状态

    private String cronExpression;// 定时任务表达式

    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date nextFireTime;// 

    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date preFireTime;// 

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("CronJobDto{");
        sb.append("cronExpression='").append(cronExpression).append('\'');
        sb.append(", group='").append(group).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", description='").append(description).append('\'');
        sb.append(", state='").append(state).append('\'');
        sb.append(", nextFireTime=").append(nextFireTime);
        sb.append(", preFireTime=").append(preFireTime);
        sb.append('}');
        return sb.toString();
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getNextFireTime() {
        return nextFireTime;
    }

    public void setNextFireTime(Date nextFireTime) {
        this.nextFireTime = nextFireTime;
    }

    public Date getPreFireTime() {
        return preFireTime;
    }

    public void setPreFireTime(Date preFireTime) {
        this.preFireTime = preFireTime;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

 创建controller类接口,实现对定时任务的控制返回状态 添加定时任务。 当然如果项目中有一个控台端这就是控台的接口

创建定时任务,暂停,重置,启动定时任务,删除以及查看总共有多少个定时任务打开

package com.jiawa.train.batch.controller;

import com.jiawa.train.batch.req.CronJobReq;
import com.jiawa.train.batch.resp.CronJobResp;
import com.jiawa.train.common.resp.CommonResp;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@RestController
@RequestMapping(value = "/admin/job")
public class JobController {

    private static Logger LOG = LoggerFactory.getLogger(JobController.class);

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @RequestMapping(value = "/run")
    public CommonResp<Object> run(@RequestBody CronJobReq cronJobReq) throws SchedulerException {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        LOG.info("手动执行任务开始:{}, {}", jobClassName, jobGroupName);
        schedulerFactoryBean.getScheduler().triggerJob(JobKey.jobKey(jobClassName, jobGroupName));
        return new CommonResp<>();
    }

    @RequestMapping(value = "/add")
    public CommonResp add(@RequestBody CronJobReq cronJobReq) {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        String cronExpression = cronJobReq.getCronExpression();
        String description = cronJobReq.getDescription();
        LOG.info("创建定时任务开始:{},{},{},{}", jobClassName, jobGroupName, cronExpression, description);
        CommonResp commonResp = new CommonResp();

        try {
            // 通过SchedulerFactory获取一个调度器实例
            Scheduler sched = schedulerFactoryBean.getScheduler();

            // 启动调度器
            sched.start();

            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(jobClassName)).withIdentity(jobClassName, jobGroupName).build();

            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName).withDescription(description).withSchedule(scheduleBuilder).build();

            sched.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException e) {
            LOG.error("创建定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("创建定时任务失败:调度异常");
        } catch (ClassNotFoundException e) {
            LOG.error("创建定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("创建定时任务失败:任务类不存在");
        }
        LOG.info("创建定时任务结束:{}", commonResp);
        return commonResp;
    }

    @RequestMapping(value = "/pause")
    public CommonResp pause(@RequestBody CronJobReq cronJobReq) {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        LOG.info("暂停定时任务开始:{},{}", jobClassName, jobGroupName);
        CommonResp commonResp = new CommonResp();
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();
            sched.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOG.error("暂停定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("暂停定时任务失败:调度异常");
        }
        LOG.info("暂停定时任务结束:{}", commonResp);
        return commonResp;
    }

    @RequestMapping(value = "/resume")
    public CommonResp resume(@RequestBody CronJobReq cronJobReq) {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        LOG.info("重启定时任务开始:{},{}", jobClassName, jobGroupName);
        CommonResp commonResp = new CommonResp();
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();
            sched.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOG.error("重启定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("重启定时任务失败:调度异常");
        }
        LOG.info("重启定时任务结束:{}", commonResp);
        return commonResp;
    }

    @RequestMapping(value = "/reschedule")
    public CommonResp reschedule(@RequestBody CronJobReq cronJobReq) {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        String cronExpression = cronJobReq.getCronExpression();
        String description = cronJobReq.getDescription();
        LOG.info("更新定时任务开始:{},{},{},{}", jobClassName, jobGroupName, cronExpression, description);
        CommonResp commonResp = new CommonResp();
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTriggerImpl trigger1 = (CronTriggerImpl) scheduler.getTrigger(triggerKey);
            trigger1.setStartTime(new Date()); // 重新设置开始时间
            CronTrigger trigger = trigger1;

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withDescription(description).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (Exception e) {
            LOG.error("更新定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("更新定时任务失败:调度异常");
        }
        LOG.info("更新定时任务结束:{}", commonResp);
        return commonResp;
    }

    @RequestMapping(value = "/delete")
    public CommonResp delete(@RequestBody CronJobReq cronJobReq) {
        String jobClassName = cronJobReq.getName();
        String jobGroupName = cronJobReq.getGroup();
        LOG.info("删除定时任务开始:{},{}", jobClassName, jobGroupName);
        CommonResp commonResp = new CommonResp();
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOG.error("删除定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("删除定时任务失败:调度异常");
        }
        LOG.info("删除定时任务结束:{}", commonResp);
        return commonResp;
    }

    @RequestMapping(value="/query")
    public CommonResp query() {
        LOG.info("查看所有定时任务开始");
        CommonResp commonResp = new CommonResp();
        List<CronJobResp> cronJobDtoList = new ArrayList();
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            for (String groupName : scheduler.getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                    CronJobResp cronJobResp = new CronJobResp();
                    cronJobResp.setName(jobKey.getName());
                    cronJobResp.setGroup(jobKey.getGroup());

                    //get job's trigger
                    List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
                    CronTrigger cronTrigger = (CronTrigger) triggers.get(0);
                    cronJobResp.setNextFireTime(cronTrigger.getNextFireTime());
                    cronJobResp.setPreFireTime(cronTrigger.getPreviousFireTime());
                    cronJobResp.setCronExpression(cronTrigger.getCronExpression());
                    cronJobResp.setDescription(cronTrigger.getDescription());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(cronTrigger.getKey());
                    cronJobResp.setState(triggerState.name());

                    cronJobDtoList.add(cronJobResp);
                }

            }
        } catch (SchedulerException e) {
            LOG.error("查看定时任务失败:" + e);
            commonResp.setSuccess(false);
            commonResp.setMessage("查看定时任务失败:调度异常");
        }
        commonResp.setContent(cronJobDtoList);
        LOG.info("查看定时任务结束:{}", commonResp);
        return commonResp;
    }

}

开始测试接口是否成功 

POST http://localhost:8000/batch/admin/job/add
Content-Type: application/json

{
  "name": "com.jiawa.train.batch.job.TestJob",
  "jobGroupName": "default",
  "cronExpression": "*/2 * * * * ?",
  "desc": "test job"
}

###

GET http://localhost:8000/batch/admin/job/query

###

POST http://localhost:8000/batch/admin/job/pause
Content-Type: application/json

{
  "name": "com.jiawa.train.batch.job.TestJob",
  "jobGroupName": "default"
}

###

POST http://localhost:8000/batch/admin/job/resume
Content-Type: application/json

{
  "name": "com.jiawa.train.batch.job.TestJob",
  "jobGroupName": "default"
}

###

POST http://localhost:8000/batch/admin/job/reschedule
Content-Type: application/json

{
"name": "com.jiawa.train.batch.job.TestJob",
"jobGroupName": "default",
"cronExpression": "*/5 * * * * ?",
"desc": "test job"
}

###

POST http://localhost:8000/batch/admin/job/delete
Content-Type: application/json

{
"name": "com.jiawa.train.batch.job.TestJob",
"jobGroupName": "default"
}

###

POST http://localhost:8000/batch/admin/job/run
Content-Type: application/json

{
"name": "com.jiawa.train.batch.job.DailyTrainJob",
"jobGroupName": "default"
}

 以上就是接口控制定时任务的开始结束添加删除的功能。

下一篇就是多节点场景中如何调度任务quartz

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot 中实现定时任务可以使用 Quartz 框架Quartz 是一个开源的作业调度框架,可以用来创建简单或复杂的作业调度程序。 下面是使用 Quartz 实现定时任务的步骤: 1. 添加 Quartz 的依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> ``` 2. 创建 Job 类 创建一个实现 org.quartz.Job 接口的 Job 类。Job 接口只有一个方法 execute(JobExecutionContext context),该方法会在作业执行时被调用。 ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } ``` 3. 创建 Trigger Trigger 是定义作业调度时间的组件。可以创建多个 Trigger 对象,每个对象对应一个时间表达式。 ```java Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); ``` 上面的代码创建了一个 Trigger 对象,它的名称是 triggerName,所属的组是 groupName。它使用了一个 Cron 表达式,表示每隔 5 秒执行一次作业。 4. 创建 Scheduler Scheduler 是 Quartz 的核心组件,用于管理和调度作业和触发器。创建一个 Scheduler 对象,然后将 Job 和 Trigger 注册到 Scheduler 中。 ```java SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); ``` 上面的代码创建了一个 Scheduler 对象,并使用 JobBuilder 和 TriggerBuilder 创建了一个 JobDetail 对象和一个 Trigger 对象。然后将 JobDetail 和 Trigger 注册到 Scheduler 中,并启动 Scheduler。 完整的代码示例: ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } public class QuartzConfig { @Bean public JobDetail jobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); } @Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); } @Bean public Scheduler scheduler() throws SchedulerException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail(), trigger()); scheduler.start(); return scheduler; } } ``` 在上面的代码中,我们使用Spring 的注解 @Bean 来注册 JobDetail、Trigger 和 Scheduler。注意要捕获 SchedulerException 异常。 这样就完成了通过集成 Quartz 来实现 SpringBoot 定时任务的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全能技术师

相关资源在博客首页资源下获取

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值