(企业 / 公司项目)如何使用分布式任务调度框架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 {@ResourceBusinessFeign 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;@Configurationpublic class QuartzConfig {/*** 声明一个任务* @return*/@Beanpublic JobDetail jobDetail() {return JobBuilder.newJob(TestJob.class).withIdentity("TestJob", "test")//  任务名称和组构成任务key.storeDurably().build();}/*** 声明一个触发器,什么时候触发这个任务* @return*/@Beanpublic 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 {@Overridepublic 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 {@Resourceprivate AutowireCapableBeanFactory beanFactory;/*** 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。*/@Overrideprotected 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 {@Resourceprivate MyJobFactory myJobFactory;@Beanpublic 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;//  执行时间表达式@Overridepublic 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;// @Overridepublic 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);@Autowiredprivate 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表达式构建一个新的triggerCronTrigger 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表达式重新构建triggertrigger = 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 triggerList<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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353989.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Spring中配置多个View解析器

1.简介 在Spring中&#xff0c;提供了View Resolver来使用模型中可用的数据来解析视图&#xff0c;而无需与JSP&#xff0c;Velocity或Thymeleaf等View技术紧密绑定。 Spring可以根据需要轻松灵活地配置一个或多个View Resolver 。 2. Spring MVC应用程序流程 在继续理解多个V…

android 知识体系

转载于:https://www.cnblogs.com/mamamia/p/8567570.html

android webview webp,iOS WebView中使用webp格式图片的方法

webp格式图片webp格式图片是google推出的&#xff0c;相比jpg png有着巨大的优势&#xff0c;同样质量的图片webp格式的图片占用空间更小&#xff0c;在像电商这样图片比较多的App中&#xff0c;使用webp格式图片会很有优势。引言很早之前&#xff0c;我们的项目中就已经采用了…

呵呵!Function构造函数

今天准备吐槽一下Function构造函数。 我们知道&#xff0c;不管是函数声明还是函数表达式都是基于词法作用域的&#xff0c;明白这点在闭包中十分重要&#xff0c;譬如&#xff1a; var aglobal; function foo(){var alocal;return function(){console.log(a);} } foo()(); …

android关机位置定位,Android5.0关机充电动画位置

充电动画位置bootable\bootloader\lk\dev\logo充电动画对应的分辨率&#xff1a;\bootable\bootloader\lk\project\XX.mkBOOT_LOGO : wxga#LOCAL_DIR : $(GET_LOCAL_DIR)TARGET : teft6752_lwt_lMODULES app/mt_boot \dev/lcmMTK_EMMC_SUPPORT yesDEFINES MTK_NEW_COMBO_EMM…

nosql的数据服务_使用NoSQL实现实体服务–第3部分:CouchDB

nosql的数据服务在本系列的第2部分中 &#xff0c;我使用SOA的“合同优先”技术创建和部署了产品实体服务&#xff0c;现在&#xff0c;我将致力于服务实现的NoSQL数据库方面。 正如我在第1部分中已经提到的那样&#xff0c;我已经选择CouchDB作为我的NoSQL数据库&#xff0c;选…

缓存穿透、缓存击穿与失效时的雪崩效应

问题&#xff0c;原理&#xff0c;解决方案转载于:https://www.cnblogs.com/tuhooo/p/8573614.html

android电视root权限获取,电视盒子/ 智能电视如何通过ADB获取ROOT权限?

如何通过adb获取root权限(安卓电视盒和智能电视通用)?Android 系统rom里面最主要的就3个文件&#xff1a;boot.img、system.img、userdata.img其中boot.img 存放着内核以及Android系统的配置信息&#xff0c;比如android系统各文件夹的读写权限&#xff0c;adb 的权限。所以如…

确定活动的热点垃圾收集器

StackOverflow问题查找正在运行哪种类型的垃圾收集 器&#xff0c;jvm的默认垃圾收集器 &#xff0c; 如何通过查看gc日志来查看正在运行的垃圾收集器&#xff1f; &#xff0c;以及如何知道HotSpot jvm的当前GC策略&#xff1f; 和博客文章如何以编程方式获取GC信息表明了人们…

spring3: Aspectj后置返回通知

Aspectj后置返回通知 接口&#xff1a; package chapter1.server;public interface IHelloService2 {public int sayAfterReturning(String param); }接口实现 package chapter1.service.impl;import chapter1.server.IHelloService2;public class HelloService2 implements IH…

Android加密通信防抓包,[原创]基于Taintdroid思想的android ssl\tsl保密通信抓包研究(未成功,分享一下思路)...

[旧帖][原创]基于Taintdroid思想的android ssl\tsl保密通信抓包研究(未成功&#xff0c;分享一下思路)0.00元2014-5-12 22:071565[旧帖][原创]基于Taintdroid思想的android ssl\tsl保密通信抓包研究(未成功&#xff0c;分享一下思路)0.00元2014-5-12 22:071565这篇文章我先在CS…

app store 关键词

如何选取关键字&#xff0c;让你的应用关键词越来越多&#xff1f; 很多朋友在做应用商店优化的时候&#xff0c;都会遇到一个让人很头疼的问题&#xff1a;如何选取关键词&#xff1f;关键词的质量直接关系到App的自然下载量&#xff0c;所以&#xff0c;我们应该用科学的办法…

android 调用微信语音识别,Android 仿微信语音识别

参考于&#xff1a;Android模仿微信语音聊天功能&#xff0c;这代码跑起来有问题&#xff0c;自己改动了一下&#xff0c;基本上没什么大问题先贴下效果图1、三个布局文件activity_main.xmldialog_manger.xmlitem_layout2.自定义的类(1)DialogMangerpackage com.nickming.view;…

android sendmessage和post的区别,handler中post和send方式区别

handler中post和send方式的区别1、从用法上send&#xff1a;发送的是Messagepost&#xff1a;发送的是Runnable对象具体用法&#xff0c;如下代码演示&#xff1a;MainActivity.javapublic class MainActivity extends AppCompatActivity {private TextView textView;private s…

耐心新来按部就班

当快速解决问题的思路行不通时&#xff0c;需要停下来&#xff0c;慢慢一步一步分析&#xff0c;找到问题根源&#xff0c;然后解决问题。转载于:https://www.cnblogs.com/Tpf386/p/8579365.html

Java:不朽的对象和对象复活

什么是对象复活&#xff1f; 当没有其他对象引用该对象时&#xff0c;该Java对象可以进行垃圾回收。 当JVM&#xff1a;s垃圾收集器最终将要删除未使用的对象时&#xff0c;将调用该对象的finalize()方法。 但是&#xff0c;如果我们再次使用对象自己的finalize()方法重新创建对…

老罗android oat,入门ART虚拟机(5)——OAT文件

Android安全交流群&#xff1a;478084054先贴老罗的一张图&#xff1a;再摘一段老罗的描述&#xff1a;“作为Android私有的一种ELF文件&#xff0c;OAT文件包含有两个特殊的段oatdata和oatexec&#xff0c;前者包含有用来生成本地机器指令的dex文件内容&#xff0c;后者包含生…

C#给字符串赋予字面值——字符串插入、转义序列的使用

1.占位符、字符串插入 给字符串赋予字面值时&#xff0c;经常遇见在字符串中包含变量的情况&#xff0c;用连接符进行拼接、转换的方式比较麻烦、还容易出错。C#提供了较为便捷的处理方式&#xff0c;即‘占位符’&#xff0c;以及C#6的新功能‘插入字符串’&#xff08;没记错…

Dajngo-Xadmin 修改菜单摆放排序

问题: Xadmin 默认是读取了所有被注册到 xadmin 的模型生成对应的菜单!这个是没问题的 ,但是xadmin又对菜单做了 "通过菜单名称" 排序.英文状态下我们的排列至少是 a-z排列的,但是一到中文就乱了,完全不符合我们的要求. 解决办法: 要到达按照我们 在 django 的 setti…

华为鸿蒙2.0什么核心,鸿蒙系统2.0:安卓最核心部分基本已去除,将带来全新的体验...

早些时候&#xff0c;华为在东莞举办的华为2020华为开发者大会如期召开&#xff0c;在大会上华为正式发布了鸿蒙系统2.0&#xff0c;并称将于明年应用到智能手机上&#xff0c;其中升级了EMUI 11的用户可以优先获得体验鸿蒙系统2.0的资格&#xff0c;瞬间将会议推向高潮。值得一…