定時任務在系統中用到的地方很多,例如每晚凌晨的數據備份,每小時獲取第三方平臺的 Token 信息等等,之前我們都是在項目中規定這個定時任務什么時候啟動,到時間了便會自己啟動,那么我們想要停止這個定時任務的時候,就需要去改動代碼,還得啟停服務器,這是非常不友好的事情
直至遇見 Quartz,利用圖形界面可視化管理定時任務,使得我們對定時任務的管理更加方便,快捷
一、Quartz 簡介
Quartz是一個開源的作業調度框架,它完全由Java寫成,并設計用于J2SE和J2EE應用中。它提供了巨大的靈 活性而不犧牲簡單性。你能夠用它來為執行一個作業而創建簡單的或復雜的調度。它有很多特征,如:數據庫支持,集群,插件,EJB作業預構 建,JavaMail及其它,支持cron-like表達式等等。
二、開發前戲
1、引入 maven 依賴
<!-- web支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Quartz 定時任務 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
這里引入了 web 的依賴,以及 Quartz 的依賴,其余依賴請根據需求自行引入
2、創建數據表
數據模型:

SQL語句:
drop table if exists sys_quartz; /*==============================================================*/ /* Table: sys_quartz */ /*==============================================================*/ create table sys_quartz ( id bigint(20) not null auto_increment comment '主鍵id', class_name varchar(32) comment '任務類名', cron_expression varchar(32) comment 'cron表達式', param varchar(32) comment '參數', descript varchar(11) comment '描述', quartz_status varchar(255) comment '啟動狀態(0--啟動1--停止)', create_time datetime comment '創建時間', create_user bigint(20) comment '創建人', status tinyint(1) default 0 comment '狀態(0--正常1--停用)', del_flag tinyint(1) default 0 comment '刪除狀態(0,正常,1已刪除)', primary key (id) ) type = InnoDB; alter table sys_quartz comment '定時任務信息表';
三、開發進行中
1、創建實體類
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.zyxx.common.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 定時任務信息表
* </p>
*
* @author lizhou
* @since 2020-07-21
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_quartz")
@ApiModel(value="SysQuartz對象", description="定時任務信息表")
public class SysQuartz extends Model<SysQuartz> {
@ApiModelProperty(value = "主鍵id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "任務類名")
@TableField("class_name")
private String className;
@ApiModelProperty(value = "cron表達式")
@TableField("cron_expression")
private String cronExpression;
@ApiModelProperty(value = "參數")
@TableField("param")
private String param;
@ApiModelProperty(value = "描述")
@TableField("descript")
private String descript;
@ApiModelProperty(value = "啟動狀態(0--啟動1--停止)")
@TableField("quartz_status")
private Integer quartzStatus;
@ApiModelProperty(value = "狀態(0--正常1--停用)")
@TableField("status")
private Integer status;
@ApiModelProperty(value = "刪除狀態(0--未刪除1--已刪除)")
@TableField("del_flag")
@TableLogic
private Integer delFlag;
@ApiModelProperty(value = "創建者")
@TableField("create_user")
private Long createUser;
@ApiModelProperty(value = "創建時間")
@TableField("create_time")
private String createTime;
@Override
protected Serializable pkVal() {
return this.id;
}
}
2、實現定時任務的 CRUD
下面我們就要完成定時任務的 新增、修改、刪除、啟停 等基本操作了,由于不是很復雜,這里的代碼就不貼出來了,貼幾張圖吧
列表頁:

新增頁:

四、定時任務
1、定時任務類
我們把定時任務都放在 job 包下面,一個定時任務就是一個文件,寫一個測試的類 TestJob.java
import com.zyxx.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* @ClassName TestJob
* 測試定時任務
* @Author Lizhou
* @Date 2020-07-21 10:58:58
**/
@Slf4j
public class TestJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("定時任務啟動:" + DateUtils.getYmdHms());
}
}
TestJob 這個類實現了 Job 接口,實現了 execute 方法,這里還可以接收參數
這個文件在 com.zyxx.sbm.job 包下面,那么在頁面新增定時任務的時候,就需要填寫任務類名為:com.zyxx.sbm.job.TestJob
cron 表達式的知識這里就不一一介紹了
2、頁面添加定時任務

那么我們的任務類名就是:com.zyxx.sbm.job.TestJob
cron 表達式:*/2 * * * * ?,表示兩秒鐘執行一次
參數:我們沒有傳入參數
3、后臺添加定時任務
package com.zyxx.sbm.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyxx.common.shiro.SingletonLoginUtils;
import com.zyxx.common.utils.DateUtils;
import com.zyxx.common.utils.LayTableResult;
import com.zyxx.common.utils.ResponseResult;
import com.zyxx.sbm.entity.SysQuartz;
import com.zyxx.sbm.mapper.SysQuartzMapper;
import com.zyxx.sbm.service.SysQuartzService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 定時任務信息表 服務實現類
* </p>
*
* @author lizhou
* @since 2020-07-21
*/
@Slf4j
@Service
public class SysQuartzServiceImpl extends ServiceImpl<SysQuartzMapper, SysQuartz> implements SysQuartzService {
@Autowired
private Scheduler scheduler;
/**
* 添加定時任務
*/
@Override
public ResponseResult add(SysQuartz sysQuartz) {
QueryWrapper<SysQuartz> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("class_name", sysQuartz.getClassName());
List<SysQuartz> sysQuartzList = list(queryWrapper);
if (null != sysQuartzList && !sysQuartzList.isEmpty()) {
return ResponseResult.getInstance().error("該任務類名已經存在");
}
sysQuartz.setCreateTime(DateUtils.getYmdHms());
sysQuartz.setCreateUser(SingletonLoginUtils.getUserId());
save(sysQuartz);
// 啟動
if (0 == sysQuartz.getQuartzStatus()) {
this.schedulerAdd(sysQuartz.getClassName().trim(), sysQuartz.getCronExpression().trim(), sysQuartz.getParam());
}
return ResponseResult.getInstance().success();
}
/**
* 添加定時任務
*
* @param className
* @param cronExpression
* @param param
*/
@Override
public void schedulerAdd(String className, String cronExpression, String param) {
try {
// 啟動調度器
scheduler.start();
// 構建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(className).getClass()).withIdentity(className).usingJobData("param", param).build();
// 表達式調度構建器(即任務執行的時間)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表達式構建一個新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(className).withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
log.error(e.getMessage());
} catch (RuntimeException e) {
log.error(e.getMessage());
} catch (Exception e) {
log.error(e.getMessage());
}
}
/**
* 刪除定時任務
*
* @param className
*/
@Override
public void schedulerDelete(String className) {
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(className));
scheduler.unscheduleJob(TriggerKey.triggerKey(className));
scheduler.deleteJob(JobKey.jobKey(className));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private static Job getClass(String className) throws Exception {
Class<?> class1 = Class.forName(className);
return (Job) class1.newInstance();
}
}
需要注入 Scheduler 對象,使用該對象開啟或停止定時任務
在啟動定時任務之前,我們應先刪除該任務類名開啟的定時任務,防止該任務類名已經添加過了
// 刪除定時任務 schedulerDelete(sysQuartz.getClassName().trim()); // 添加定時任務 schedulerAdd(sysQuartz.getClassName().trim(), sysQuartz.getCronExpression().trim(), sysQuartz.getParam());
添加定時任務,傳入任務類名,cron 表達式,參數
停止定時任務,只需要:
scheduler.pauseJob(JobKey.jobKey(sysQuartz.getClassName().trim()));
根據任務類名,停止定時任務即可
五、開發測試
啟動項目,在管理界面,開啟定時任務,即可在控制臺看到打印的信息

表示我們的定時任務已經啟動成功了
六、優化建議
當我們添加了定時任務并啟動后,重新啟動項目的時候,定時任務卻不會自動啟動,這時候,我們就需要在項目啟動的時候做一些事情了,也就是系統啟動任務
不清楚的同學可以復習一下之前我的博客【SpringBoot】十九、SpringBoot中實現啟動任務
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyxx.sbm.entity.SysQuartz;
import com.zyxx.sbm.service.SysQuartzService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @ClassName SystemStartTask
* 項目啟動任務--啟動定時任務
* @Author Lizhou
* @Date 2020-07-21 12:56:56
**/
@Component
@Order(100)
public class SystemQuartzStartTask implements CommandLineRunner {
@Autowired
private SysQuartzService sysQuartzService;
@Override
public void run(String... args) throws Exception {
// 查詢啟動的定時任務
QueryWrapper<SysQuartz> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("status", 0);
queryWrapper.eq("quartz_status", 0);
List<SysQuartz> list = sysQuartzService.list(queryWrapper);
if (null != list && !list.isEmpty()) {
for (SysQuartz item : list) {
// 刪除定時任務
sysQuartzService.schedulerDelete(item.getClassName().trim());
// 添加定時任務
sysQuartzService.schedulerAdd(item.getClassName().trim(), item.getCronExpression().trim(), item.getParam());
}
}
}
}
從數據庫查詢出啟動的定時任務,并將他們添加到定時任務啟動中,這樣項目一啟動時,就會自動啟動我們定義的定時任務了
最后
任務類名的正則表達式
/^[a-zA-Z]+(\.([a-zA-Z])+)+$/
cron 表達式的驗證使用正則太麻煩,可以使用 Quartz 自帶驗證方法
CronExpression.isValidExpression(cron)
SpringBoot 中使用 Quartz 管理定時任務的學習就到這兒了,其實也并不難理解,相比于之前用的定時任務是不是好很多了呢,別忘了最后加上系統啟動任務哦
總結
到此這篇關于SpringBoot中使用Quartz管理定時任務的文章就介紹到這了,更多相關SpringBoot管理定時任務內容請搜索億速云以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。