spring boot集成quartz,实现动态增删改定时任务
1.建立实体类
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
@Data
public class QuartzInfo {
@JsonIgnore
private Integer id;
/*任务名称*/
private String jobName;
/*任务执行类*/
private String jobClass;
/*任务描述*/
private String jobDescription;
/*触发器名称*/
private String triggerName;
/* 任务运行时间表达式 */
private String cronExpression;
/*触发器描述*/
private String triggerDescription;
/*任务状态 运行中 1 暂停 0 */
private Integer status = 1;
}
2.编写quartz工具类
import com.huaiwei.springbootquartz.domian.QuartzInfo;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
public class QuartzUtil {
private final Scheduler scheduler;
private final JdbcTemplate template;
/**
* 初始化所有定时任务
*
* @param scheduler 调度器
* @param template jdbcApi
*/
@Autowired
public QuartzUtil(Scheduler scheduler, JdbcTemplate template) {
this.scheduler = scheduler;
this.template = template;
String sql = "select * from quartz_info where status = 1 ";
/*从数据库中查询所有状态为1的定时任务*/
List<QuartzInfo> list = this.template.query(sql, new BeanPropertyRowMapper<>(QuartzInfo.class));
for (QuartzInfo info : list) {
this.createJob(info);
}
}
/**
* 创建定时任务
*
* @param info quartz信息bean
*/
public void createJob(QuartzInfo info) {
Class<? extends Job> clz = null;
try {
clz = (Class<? extends Job>) Class.forName(info.getJobClass());
} catch (ClassNotFoundException e) {
log.error("job类出错", e);
}
JobDetail detail = JobBuilder.newJob(clz)
.withDescription(info.getJobDescription())
.withIdentity(info.getJobName())
.build();
CronScheduleBuilder cronSchedule = null;
try {
cronSchedule = CronScheduleBuilder.cronSchedule(info.getCronExpression());
} catch (Exception e) {
log.error("cron表达式出错", e);
}
CronTrigger cron = TriggerBuilder.newTrigger().withDescription(info.getTriggerDescription())
.withIdentity(info.getTriggerName())
.withSchedule(cronSchedule)
.startNow()
.build();
try {
scheduler.scheduleJob(detail, cron);
/*保存QuartzInfo*/
String sql = "insert into quartz_info(job_name,job_class,job_description,trigger_Name,cronExpression,trigger_Description) " +
"values(?,?,?,?,?,?)";
if (info.getId() == null || info.getId() == -1) {
template.update(sql, info.getJobName(), info.getJobClass(),
info.getJobDescription(), info.getTriggerName(), info.getCronExpression(), info.getTriggerDescription());
}
} catch (SchedulerException e) {
log.error("调度定时任务出错", e);
}
}
/**
* 根据定时任务名称从调度器当中删除定时任务
*
* @param jobName 任务名称(唯一)
*/
public void deleteScheduleJob(String jobName) {
JobKey jobKey = JobKey.jobKey(jobName);
try {
scheduler.deleteJob(jobKey);
/*删除 QuartzInfo */
String sql = "delete from quartz_info where job_name = ?";
template.update(sql, jobName);
} catch (SchedulerException e) {
log.error("删除定时任务出错", e);
}
}
/**
* 根据任务名称暂停定时任务
*
* @param jobName 任务名称(唯一)
*/
public void pauseScheduleJob(String jobName) {
JobKey jobKey = JobKey.jobKey(jobName);
try {
scheduler.pauseJob(jobKey);
/*修改info 状态为暂停*/
String sql = "update quartz_info set status = 0 where job_Name = ?";
template.update(sql, jobName);
} catch (SchedulerException e) {
log.error("暂停定时任务出错", e);
}
}
/**
* 根据任务名称恢复定时任务
*
* @param jobName 任务名称(唯一)
*/
public void resumeScheduleJob(String jobName) {
JobKey jobKey = JobKey.jobKey(jobName);
try {
scheduler.resumeJob(jobKey);
/*修改status数据为正运行*/
String sql = "update quartz_info set status = 1 where job_Name = ?";
template.update(sql, jobName);
} catch (SchedulerException e) {
log.error("恢复定时任务出错", e);
}
}
/**
* 更新定时任务
*
* @param triggerName 调度器名称
*/
public void updateScheduleJob(String triggerName, String cronExpression) {
try {
//获取到对应任务的触发器
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
//设置定时任务执行方式
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//重新构建任务的触发器trigger
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//重置对应的job
scheduler.rescheduleJob(triggerKey, trigger);
/*更新数据库信息*/
String sql = "update quartz_info set cronExpression = ? where trigger_Name = ? ";
template.update(sql, cronExpression, triggerName);
} catch (SchedulerException e) {
log.error("更新定时任务出错", e);
}
}
/**
* 所有定时任务列表
*
* @return List<QuartzInfo>
*/
public List<QuartzInfo> quartzInfoList() {
String sql = "select * from quartz_info";
return template.query(sql, new BeanPropertyRowMapper<>(QuartzInfo.class));
}
}
3.编写controller
import com.huaiwei.springbootquartz.domian.QuartzInfo;
import com.huaiwei.springbootquartz.utils.QuartzUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/quartz")
public class QuartzController {
private final QuartzUtil quartzUtil;
@Autowired
public QuartzController(QuartzUtil quartzUtil) {
this.quartzUtil = quartzUtil;
}
@PostMapping("/create")
public String createJob(@RequestBody QuartzInfo info) {
quartzUtil.createJob(info);
return "创建成功";
}
@PutMapping("/update")
public String updateJob(String triggerName, String cronExpression) {
quartzUtil.updateScheduleJob(triggerName, cronExpression);
return "更新成功";
}
@GetMapping("/pause/{jobName}")
public String pauseJob(@PathVariable String jobName) {
quartzUtil.pauseScheduleJob(jobName);
return "暂停成功";
}
@DeleteMapping("/delete/{jobName}")
public String deleteJob(@PathVariable String jobName) {
quartzUtil.deleteScheduleJob(jobName);
return "删除成功";
}
@GetMapping("/resumeJob/{jobName}")
public String resumeJob(@PathVariable String jobName) {
quartzUtil.resumeScheduleJob(jobName);
return "恢复成功";
}
@GetMapping("/list")
public List<QuartzInfo> ListJob() {
return quartzUtil.quartzInfoList();
}
}
4.测试
本人使用swagger2测试,具体环境小伙伴可使用postman测试,简单又方便。
1. 启动项目,jdbctemplate 能如期的查出定时任务并和项目一起启动执行
2. 测试增删改定时任务成功,能如期运行
3. 达到如期结果
5.总结
网上搜了很多篇博客,大部分没有写出自己想要的结果,而且有些博文中使用技术过老,就例如我在代码编写的过程中发现并不需要实现ApplicationContextAware 接口来来获取Scheduler对象,也没有遇到在任务类注入对象失败的情况。可能是我用的jar比较新吧,总之,若有问题,欢迎各位批评指正。