1、在pom.xml文件中导入quartz的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、配置quartz的数据源等操作
package com.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);
// 启动之后2秒后可以执行
factory.setStartupDelay(2);
return factory;
}
}
需要对父类的方法进行重写。
package com.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;
}
}
3、并发执行:上一周期还没执行完,下一周期又开始了
禁止任务并发执行,只需要在类上加一个注解(@DisallowConcurrentExecution)
4、controller类,
做调度问题,不应该把任务写在配置类里面,应该用控制台增加,以下的文件直接拿来用就行。
package com.train.batch.job;
import com.train.batch.req.CronJobReq;
import com.train.batch.resp.CronJobResp;
import com.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;
}
}
5、DOM类的相关定义
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;
}
}
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;
}
}