1. 程式人生 > 程式設計 >Springboot2.x+Quartz分散式叢集的實現

Springboot2.x+Quartz分散式叢集的實現

生產環境一般都是多節點高可用,Springboot本身自帶有定時任務功能,但我們專案需求要求能對定時任務進行增,刪,改,查。所以考慮引進Quartz,引入Quartz就需要考慮分散式叢集,所以就有了這篇文章。

資料庫指令碼

Quartz資料庫有11張表,既支援Mysql,也支援Oracle

Mysql

/*
Navicat MySQL Data Transfer

Source Server     : 10.19.34.3_ehr_admin
Source Server Version : 50639
Source Host      : 10.19.34.3:3306
Source Database    : attend_base_dev

Target Server Type  : MYSQL
Target Server Version : 50639
File Encoding     : 65001

Date: 2020-08-28 16:29:36
*/

-- SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `qrtz_CALENDARS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_CALENDARS`;
CREATE TABLE `qrtz_CALENDARS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`CALENDAR_NAME` varchar(200) NOT NULL,`CALENDAR` blob NOT NULL,PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='日曆資訊';

-- ----------------------------
-- Records of qrtz_CALENDARS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_FIRED_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_FIRED_TRIGGERS`;
CREATE TABLE `qrtz_FIRED_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`ENTRY_ID` varchar(95) NOT NULL COMMENT '組標識',`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` int(11) NOT NULL COMMENT '權重',`STATE` varchar(16) NOT NULL COMMENT '狀態:WAITING:等待 \r\nPAUSED:暫停 \r\nACQUIRED:正常執行 \r\nBLOCKED:阻塞 \r\nERROR:錯誤',`JOB_NAME` varchar(200) DEFAULT NULL COMMENT '作業名稱',`JOB_GROUP` varchar(200) DEFAULT NULL COMMENT '作業組',`IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否並行',`REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否要求喚醒',`ENTRY_ID`),KEY `IDX_qrtz_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),KEY `IDX_qrtz_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),KEY `IDX_qrtz_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),KEY `IDX_qrtz_FT_JG` (`SCHED_NAME`,KEY `IDX_qrtz_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),KEY `IDX_qrtz_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='儲存已經觸發的觸發器狀態資訊';

-- ----------------------------
-- Records of qrtz_FIRED_TRIGGERS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_JOB_DETAILS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_JOB_DETAILS`;
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) DEFAULT NULL COMMENT '描述',`JOB_CLASS_NAME` varchar(250) NOT NULL COMMENT '作業程式類名',`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,KEY `IDX_qrtz_J_REQ_RECOVERY` (`SCHED_NAME`,KEY `IDX_qrtz_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='job 詳細資訊';

-- ----------------------------
-- Records of qrtz_JOB_DETAILS
-- ----------------------------
-- ----------------------------
-- Table structure for `qrtz_LOCKS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_LOCKS`;
CREATE TABLE `qrtz_LOCKS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`LOCK_NAME` varchar(40) NOT NULL COMMENT '鎖名稱',`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='儲存程式的悲觀鎖的資訊(假如使用了悲觀鎖) ';

-- ----------------------------
-- Records of qrtz_LOCKS

-- ----------------------------
-- Table structure for `qrtz_PAUSED_TRIGGER_GRPS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_PAUSED_TRIGGER_GRPS`;
CREATE TABLE `qrtz_PAUSED_TRIGGER_GRPS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存放暫停掉的觸發器';

-- ----------------------------
-- Records of qrtz_PAUSED_TRIGGER_GRPS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_SCHEDULER_STATE`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_SCHEDULER_STATE`;
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 '檢查間隔',`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='排程器狀態';

-- ----------------------------
-- Records of qrtz_SCHEDULER_STATE

-- ----------------------------
-- Table structure for `qrtz_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_TRIGGERS`;
CREATE TABLE `qrtz_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`JOB_NAME` varchar(200) NOT NULL COMMENT '作業名稱',`JOB_GROUP` varchar(200) NOT NULL COMMENT '作業組',`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '下次執行時間',`PREV_FIRE_TIME` bigint(13) DEFAULT NULL COMMENT '前一次',`PRIORITY` int(11) DEFAULT 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) DEFAULT NULL COMMENT '結束時間',`CALENDAR_NAME` varchar(200) DEFAULT NULL COMMENT '日曆名稱',`MISFIRE_INSTR` smallint(2) DEFAULT NULL COMMENT '失敗次數',KEY `IDX_qrtz_T_J` (`SCHED_NAME`,KEY `IDX_qrtz_T_JG` (`SCHED_NAME`,KEY `IDX_qrtz_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),KEY `IDX_qrtz_T_G` (`SCHED_NAME`,KEY `IDX_qrtz_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),KEY `IDX_qrtz_T_N_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,KEY `IDX_qrtz_T_N_G_STATE` (`SCHED_NAME`,KEY `IDX_qrtz_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),KEY `IDX_qrtz_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,KEY `IDX_qrtz_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,KEY `IDX_qrtz_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`NEXT_FIRE_TIME`,KEY `IDX_qrtz_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`TRIGGER_STATE`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='觸發器';

-- ----------------------------
-- Records of qrtz_TRIGGERS

-- ----------------------------
-- Table structure for `qrtz_SIMPLE_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_SIMPLE_TRIGGERS`;
CREATE TABLE `qrtz_SIMPLE_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重複次數',`REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重複間隔',`TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '觸發次數',`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='簡單的觸發器';

-- ----------------------------
-- Records of qrtz_SIMPLE_TRIGGERS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_SIMPROP_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_SIMPROP_TRIGGERS`;
CREATE TABLE `qrtz_SIMPROP_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`STR_PROP_1` varchar(512) DEFAULT NULL,`STR_PROP_2` varchar(512) DEFAULT NULL,`STR_PROP_3` varchar(512) DEFAULT NULL,`INT_PROP_1` int(11) DEFAULT NULL,`INT_PROP_2` int(11) DEFAULT NULL,`LONG_PROP_1` bigint(20) DEFAULT NULL,`LONG_PROP_2` bigint(20) DEFAULT NULL,`DEC_PROP_1` decimal(13,4) DEFAULT NULL,`DEC_PROP_2` decimal(13,`BOOL_PROP_1` varchar(1) DEFAULT NULL,`BOOL_PROP_2` varchar(1) DEFAULT NULL,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='儲存CalendarIntervalTrigger和DailyTimeIntervalTrigger兩種型別的觸發器';

-- ----------------------------
-- Records of qrtz_SIMPROP_TRIGGERS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_BLOB_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_BLOB_TRIGGERS`;
CREATE TABLE `qrtz_BLOB_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名',`BLOB_DATA` blob,KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以Blob 型別儲存的觸發器';

-- ----------------------------
-- Records of qrtz_BLOB_TRIGGERS
-- ----------------------------

-- ----------------------------
-- Table structure for `qrtz_CRON_TRIGGERS`
-- ----------------------------
-- DROP TABLE IF EXISTS `qrtz_CRON_TRIGGERS`;
CREATE TABLE `qrtz_CRON_TRIGGERS` (
 `SCHED_NAME` varchar(120) NOT NULL COMMENT '計劃名稱',`CRON_EXPRESSION` varchar(120) NOT NULL COMMENT '時間表達式',`TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '時區ID   nvarchar   80',`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='定時觸發器';

-- ----------------------------
-- Records of qrtz_CRON_TRIGGERS
-- ----------------------------
Oracle
create table QRTZ_CALENDARS
(
 sched_name  VARCHAR2(120) not null,calendar_name VARCHAR2(200) not null,calendar   BLOB not null
);
alter table QRTZ_CALENDARS
 add constraint PK_QRTZ_CALENDARS primary key (SCHED_NAME,CALENDAR_NAME);

create table QRTZ_FIRED_TRIGGERS
(
 sched_name    VARCHAR2(120) not null,entry_id     VARCHAR2(95) not null,trigger_name   VARCHAR2(200) not null,trigger_group   VARCHAR2(200) not null,instance_name   VARCHAR2(200) not null,fired_time    NUMBER(13) not null,sched_time    NUMBER(13) not null,priority     INTEGER not null,state       VARCHAR2(16) not null,job_name     VARCHAR2(200),job_group     VARCHAR2(200),is_nonconcurrent VARCHAR2(1),requests_recovery VARCHAR2(1)
);
alter table QRTZ_FIRED_TRIGGERS
 add constraint PK_QRTZ_FIRED_TRIGGERS primary key (SCHED_NAME,ENTRY_ID);

create table QRTZ_JOB_DETAILS
(
 sched_name    VARCHAR2(120) not null,job_name     VARCHAR2(200) not null,job_group     VARCHAR2(200) not null,description    VARCHAR2(250),job_class_name  VARCHAR2(250) not null,is_durable    VARCHAR2(1) not null,is_nonconcurrent VARCHAR2(1) not null,is_update_data  VARCHAR2(1) not null,requests_recovery VARCHAR2(1) not null,job_data     BLOB
);
alter table QRTZ_JOB_DETAILS
 add constraint PK_QRTZ_JOB_DETAILS primary key (SCHED_NAME,JOB_NAME,JOB_GROUP);

create table QRTZ_LOCKS
(
 sched_name VARCHAR2(120) not null,lock_name VARCHAR2(40) not null
);
alter table QRTZ_LOCKS
 add constraint PK_QRTZ_LOCKS primary key (SCHED_NAME,LOCK_NAME);

create table QRTZ_PAUSED_TRIGGER_GRPS
(
 sched_name  VARCHAR2(120) not null,trigger_group VARCHAR2(200) not null
);
alter table QRTZ_PAUSED_TRIGGER_GRPS
 add constraint PK__TRIGGER_GRPS primary key (SCHED_NAME,TRIGGER_GROUP);

create table QRTZ_SCHEDULER_STATE
(
 sched_name    VARCHAR2(120) not null,last_checkin_time NUMBER(13) not null,checkin_interval NUMBER(13) not null
);
alter table QRTZ_SCHEDULER_STATE
 add constraint PK_QRTZ_SCHEDULER_STATE primary key (SCHED_NAME,INSTANCE_NAME);

create table QRTZ_TRIGGERS
(
 sched_name   VARCHAR2(120) not null,trigger_name  VARCHAR2(200) not null,trigger_group VARCHAR2(200) not null,job_name    VARCHAR2(200) not null,job_group   VARCHAR2(200) not null,description  VARCHAR2(250),next_fire_time NUMBER(13),prev_fire_time NUMBER(13),priority    INTEGER,trigger_state VARCHAR2(16) not null,trigger_type  VARCHAR2(8) not null,start_time   NUMBER(13) not null,end_time    NUMBER(13),calendar_name VARCHAR2(200),misfire_instr NUMBER(2),job_data    BLOB
);

alter table QRTZ_TRIGGERS
 add constraint PK_QRTZ_TRIGGERS primary key (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);

create table QRTZ_SIMPLE_TRIGGERS
(
 sched_name   VARCHAR2(120) not null,trigger_group  VARCHAR2(200) not null,repeat_count  NUMBER(7) not null,repeat_interval NUMBER(12) not null,times_triggered NUMBER(10) not null
);
alter table QRTZ_SIMPLE_TRIGGERS
 add constraint PK_QRTZ_SIMPLE_TRIGGERS primary key (SCHED_NAME,TRIGGER_GROUP);

create table QRTZ_SIMPROP_TRIGGERS
(
 sched_name  VARCHAR2(120) not null,trigger_name VARCHAR2(200) not null,str_prop_1  VARCHAR2(512),str_prop_2  VARCHAR2(512),str_prop_3  VARCHAR2(512),int_prop_1  INTEGER,int_prop_2  INTEGER,long_prop_1  NUMBER,long_prop_2  NUMBER,dec_prop_1  NUMBER(13,4),dec_prop_2  NUMBER(13,bool_prop_1  VARCHAR2(1),bool_prop_2  VARCHAR2(1)
);
alter table QRTZ_SIMPROP_TRIGGERS
 add constraint PK_QRTZ_SIMPROP_TRIGGERS primary key (SCHED_NAME,TRIGGER_GROUP);

create table QRTZ_BLOB_TRIGGERS
(
 sched_name  VARCHAR2(120) not null,blob_data   BLOB
);
alter table QRTZ_BLOB_TRIGGERS
 add constraint PK_QRTZ_BLOB_TRIGGERS primary key (SCHED_NAME,TRIGGER_GROUP);

create table QRTZ_CRON_TRIGGERS
(
 sched_name   VARCHAR2(120) not null,cron_expression VARCHAR2(200) not null,time_zone_id  VARCHAR2(80)
);
alter table QRTZ_CRON_TRIGGERS
 add constraint PK_QRTZ_CRON_TRIGGERS primary key (SCHED_NAME,TRIGGER_GROUP);

delete from QRTZ_JOB_DETAILS;
delete from QRTZ_CRON_TRIGGERS;
delete from QRTZ_BLOB_TRIGGERS;
delete from QRTZ_CALENDARS;
delete from QRTZ_FIRED_TRIGGERS;
delete from QRTZ_LOCKS;
delete from QRTZ_PAUSED_TRIGGER_GRPS;
delete from QRTZ_SCHEDULER_STATE;
delete from QRTZ_SIMPLE_TRIGGERS;
delete from QRTZ_SIMPROP_TRIGGERS;
delete from QRTZ_TRIGGERS;

Maven

我這裡後臺使用的是Springboot2.1

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

application.yml

quartz:
  #quartz相關屬性配置
  properties:
   org:
    quartz:
     scheduler:
      instanceName: clusteredScheduler #排程器的例項名
      instanceId: AUTO #排程器編號自動生成
     jobStore:
      class: org.quartz.impl.jdbcjobstore.JobStoreTX
      driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
      tablePrefix: qrtz_ #資料庫表名字首
      isClustered: true #開啟分散式部署
      clusterCheckinInterval: 10000 #分散式節點有效性檢查時間間隔,單位:秒
      useProperties: false
     threadPool:
      class: org.quartz.simpl.SimpleThreadPool #自帶的執行緒池實現類
      threadCount: 10 #開啟10個執行緒
      threadPriority: 5 #工作者執行緒的優先順序
      threadsInheritContextClassLoaderOfInitializingThread: true
  #資料庫方式
  job-store-type: jdbc

Bean

import org.quartz.JobDataMap;
import java.util.Date;

/**
 * @program: QuartzBean 
 * @description:
 * @author: Yuwl
 * @create: 2020-06-02 18:36
 **/
public class QuartzBean {

  /** 任務id */
  private String id;

  /** 任務名稱 */
  private String jobName;

  /** 任務組 */
  private String jobGroup;

  /** 任務執行類 */
  private String jobClass;

  /** 任務狀態 啟動還是暫停*/
  private Integer status;

  /**
   * 任務開始時間
   */
  private Date startTime;

  /**
   * 任務迴圈間隔-單位:分鐘
   */
  private Integer interval;

  /**
   * 任務結束時間
   */
  private Date endTime;

  /** 任務執行時間表達式 */
  private String cronExpression;

  private JobDataMap jobDataMap;

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getJobName() {
    return jobName;
  }

  public void setJobName(String jobName) {
    this.jobName = jobName;
  }

  public String getJobClass() {
    return jobClass;
  }

  public void setJobClass(String jobClass) {
    this.jobClass = jobClass;
  }

  public Integer getStatus() {
    return status;
  }

  public void setStatus(Integer status) {
    this.status = status;
  }

  public String getCronExpression() {
    return cronExpression;
  }

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

  public Date getStartTime() {
    return startTime;
  }

  public void setStartTime(Date startTime) {
    this.startTime = startTime;
  }

  public Integer getInterval() {
    return interval;
  }

  public void setInterval(Integer interval) {
    this.interval = interval;
  }

  public Date getEndTime() {
    return endTime;
  }

  public void setEndTime(Date endTime) {
    this.endTime = endTime;
  }

  public JobDataMap getJobDataMap() {
    return jobDataMap;
  }

  public void setJobDataMap(JobDataMap jobDataMap) {
    this.jobDataMap = jobDataMap;
  }

  public String getJobGroup() {
    return jobGroup;
  }

  public void setJobGroup(String jobGroup) {
    this.jobGroup = jobGroup;
  }
}

Service

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.framework.quartz.QuartzBean;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @program: QuartzJobService 
 * @description:
 * @author: Yuwl
 * @create: 2020-07-21 17:00
 **/
@Service
public class QuartzJobService {

  @Autowired
  private Scheduler scheduler;

  /**
   * 建立定時任務Simple
   * quartzBean.getInterval()==null表示單次提醒,
   * 否則迴圈提醒(quartzBean.getEndTime()!=null)
   * @param quartzBean
   */
  public void createScheduleJobSimple(QuartzBean quartzBean) throws Exception{
    //獲取到定時任務的執行類 必須是類的絕對路徑名稱
    //定時任務類需要是job類的具體實現 QuartzJobBean是job的抽象類。
    Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
    // 構建定時任務資訊
    JobDetail jobDetail = JobBuilder.newJob(jobClass)
        .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
        .setJobData(quartzBean.getJobDataMap())
        .build();
    // 設定定時任務執行方式
    SimpleScheduleBuilder simpleScheduleBuilder = null;
    if (quartzBean.getInterval() == null) { //單次
      simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
    } else { //迴圈
      simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());
    }
    // 構建觸發器trigger
    Trigger trigger = null;
    if (quartzBean.getInterval() == null) { //單次
      trigger = TriggerBuilder.newTrigger()
          .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
          .withSchedule(simpleScheduleBuilder)
          .startAt(quartzBean.getStartTime())
          .build();
    } else { //迴圈
      trigger = TriggerBuilder.newTrigger()
          .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
          .withSchedule(simpleScheduleBuilder)
          .startAt(quartzBean.getStartTime())
          .endAt(quartzBean.getEndTime())
          .build();
    }
    scheduler.scheduleJob(jobDetail,trigger);
  }

  /**
   * 建立定時任務Cron
   * 定時任務建立之後預設啟動狀態
   * @param quartzBean 定時任務資訊類
   * @throws Exception
   */
  public void createScheduleJobCron(QuartzBean quartzBean) throws Exception{
    //獲取到定時任務的執行類 必須是類的絕對路徑名稱
    //定時任務類需要是job類的具體實現 QuartzJobBean是job的抽象類。
    Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
    // 構建定時任務資訊
    JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).setJobData(quartzBean.getJobDataMap()).build();
    // 設定定時任務執行方式
    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
    // 構建觸發器trigger
    CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
    scheduler.scheduleJob(jobDetail,trigger);
  }

  /**
   * 根據任務名稱暫停定時任務
   * @param jobName 定時任務名稱
   * @param jobGroup 任務組(沒有分組傳值null)
   * @throws Exception
   */
  public void pauseScheduleJob(String jobName,String jobGroup) throws Exception{
    JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    scheduler.pauseJob(jobKey);
  }

  /**
   * 根據任務名稱恢復定時任務
   * @param jobName  定時任務名
   * @param jobGroup 任務組(沒有分組傳值null)
   * @throws SchedulerException
   */
  public void resumeScheduleJob(String jobName,String jobGroup) throws Exception {
    JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    scheduler.resumeJob(jobKey);
  }

  /**
   * 根據任務名稱立即執行一次定時任務
   * @param jobName    定時任務名稱
   * @param jobGroup 任務組(沒有分組傳值null)
   * @throws SchedulerException
   */
  public void runOnce(String jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    scheduler.triggerJob(jobKey);
  }

  /**
   * 更新定時任務Simple
   * @param quartzBean 定時任務資訊類
   * @throws SchedulerException
   */
  public void updateScheduleJobSimple(QuartzBean quartzBean) throws Exception {
    //獲取到對應任務的觸發器
    TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null);
    // 設定定時任務執行方式
    SimpleScheduleBuilder simpleScheduleBuilder = null;
    if (quartzBean.getInterval() == null) { //單次
      simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
    } else { //迴圈
      simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval());
    }
    // 構建觸發器trigger
    Trigger trigger = null;
    if (quartzBean.getInterval() == null) { //單次
      trigger = TriggerBuilder.newTrigger()
          .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
          .withSchedule(simpleScheduleBuilder)
          .startAt(quartzBean.getStartTime())
          .build();
    } else { //迴圈
      TriggerBuilder.newTrigger()
          .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup():null)
          .withSchedule(simpleScheduleBuilder)
          .startAt(quartzBean.getStartTime())
          .endAt(quartzBean.getEndTime())
          .build();
    }
    //重置對應的job
    scheduler.rescheduleJob(triggerKey,trigger);
  }

  /**
   * 更新定時任務Cron
   * @param quartzBean 定時任務資訊類
   * @throws SchedulerException
   */
  public void updateScheduleJobCron(QuartzBean quartzBean) throws Exception {
    //獲取到對應任務的觸發器
    TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
    //設定定時任務執行方式
    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
    //重新構建任務的觸發器trigger
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
    //重置對應的job
    scheduler.rescheduleJob(triggerKey,trigger);
  }

  /**
   * 根據定時任務名稱從排程器當中刪除定時任務
   * @param jobName  定時任務名稱
   * @param jobGroup 任務組(沒有分組傳值null)
   * @throws SchedulerException
   */
  public void deleteScheduleJob(String jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    scheduler.deleteJob(jobKey);
  }

  /**
   * 獲取任務狀態
   * @param jobName
   * @param jobGroup 任務組(沒有分組傳值null)
   * @return
   * (" BLOCKED "," 阻塞 ");
   * ("COMPLETE","完成");
   * ("ERROR","出錯");
   * ("NONE","不存在");
   * ("NORMAL","正常");
   * ("PAUSED","暫停");
   */
  public String getScheduleJobStatus(String jobName,String jobGroup) throws Exception {
    TriggerKey triggerKey = TriggerKey.triggerKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
    return state.name();
  }

  /**
   * 根據定時任務名稱來判斷任務是否存在
   * @param jobName  定時任務名稱
   * @param jobGroup 任務組(沒有分組傳值null)
   * @throws SchedulerException
   */
  public Boolean checkExistsScheduleJob(String jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    return scheduler.checkExists(jobKey);
  }

  /**
   * 根據任務組刪除定時任務
   * @param jobGroup 任務組
   * @throws SchedulerException
   */
  public Boolean deleteGroupJob(String jobGroup) throws Exception {
    GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup);
    Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher);
    List<JobKey> jobkeyList = new ArrayList<JobKey>();
    jobkeyList.addAll(jobkeySet);
    return scheduler.deleteJobs(jobkeyList);
  }

  /**
   * 根據任務組批量刪除定時任務
   * @param jobkeyList
   * @throws SchedulerException
   */
  public Boolean batchDeleteGroupJob(List<JobKey> jobkeyList) throws Exception {
    return scheduler.deleteJobs(jobkeyList);
  }

  /**
   * 根據任務組批量查詢出jobkey
   * @param jobGroup 任務組
   * @throws SchedulerException
   */
  public void batchQueryGroupJob(List<JobKey> jobkeyList,String jobGroup) throws Exception {
    GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup);
    Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher);
    jobkeyList.addAll(jobkeySet);
  }
}

Job

package com.quartz.demo.job

import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @program: job
 * @description:
 * @author: Yuwl
 * @create: 2020-06-02 18:07
 **/
@Component
public class MyTask extends QuartzJobBean {
  @Override
  protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    JobKey jobKey = context.getJobDetail().getKey();
    JobDataMap map = context.getJobDetail().getJobDataMap();
    String userId = map.getString("userId");
    System.out.println("SimpleJob says: " + jobKey + ",userId: " + userId + " executing at " + new Date());
  }
}

Controller

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.quartz.QuartzBean;
import com.ruoyi.framework.quartz.service.QuartzJobService;
import org.quartz.JobDataMap;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.util.Date;

/**
 * @program: JobController 
 * @description:
 * @author: Yuwl
 * @create: 2020-07-21 17:08
 **/
@RestController
@RequestMapping("/api/quartz/")
public class JobController {

  @Autowired
  private QuartzJobService quartzJobService;

  //建立&啟動
  @GetMapping("startSimpleJob")
  public String startSimpleJob() throws SchedulerException,ClassNotFoundException,ParseException {
    QuartzBean quartzBean = new QuartzBean();
    quartzBean.setJobClass("com.quartz.demo.job.MyTask");
    quartzBean.setJobName("job1");
    JobDataMap map = new JobDataMap();
    map.put("userId","123456");
    quartzBean.setJobDataMap(map);
    Date now = new Date();
    quartzBean.setStartTime(DateUtils.addSeconds(now,10));
    quartzBean.setInterval(10);
    quartzBean.setEndTime(DateUtils.addMinutes(now,1));
    try {
      quartzJobService.createScheduleJobSimple(quartzBean);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "startJob Success!";
  }

  /**
   * 建立cron Job
   * @param quartzBean
   * @return
   */
  @RequestMapping("/createCronJob")
  @ResponseBody
  public String createJob(QuartzBean quartzBean) {
    try {
      //進行測試所以寫死
      quartzBean.setJobClass("com.quartz.demo.job.MyTask");
      quartzBean.setJobName("job1");
      quartzBean.setCronExpression("*/5 * * * * ?");
      quartzJobService.createScheduleJobCron(quartzBean);
    } catch (Exception e) {
      return "建立失敗";
    }
    return "建立成功";
  }

  /**
   * 暫停job
   * @return
   */
  @RequestMapping(value = {"/pauseJob/{jobName}","/pauseJob/{jobName}/{jobGroup}"})
  @ResponseBody
  public String pauseJob(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
    try {
    quartzJobService.pauseScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    } catch (Exception e) {
      return "暫停失敗";
    }
    return "暫停成功";
  }

  @RequestMapping(value = {"/resume/{jobName}","/resume/{jobName}/{jobGroup}"})
  @ResponseBody
  public String resume(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
    try {
  quartzJobService.resumeScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    } catch (Exception e) {
      return "啟動失敗";
    }
    return "啟動成功";
  }

  @RequestMapping(value = {"/delete/{jobName}","/delete/{jobName}/{jobGroup}"})
  public String delete(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
    try {
      quartzJobService.deleteScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    } catch (Exception e) {
      return "刪除失敗";
    }
    return "刪除成功";
  }

  @RequestMapping(value = {"/check/{jobName}","/check/{jobName}/{jobGroup}"})
  public String check(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
    try {
      if(quartzJobService.checkExistsScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null)){
        return "存在定時任務:"+jobName;
      }else{
        return "不存在定時任務:"+jobName;
      }
    } catch (Exception e) {
      return "查詢任務失敗";
    }
  }

  @RequestMapping(value = {"/status/{jobName}","/status/{jobName}/{jobGroup}"})
  @ResponseBody
  public String status(@PathVariable("jobName") String jobName,@PathVariable(required = false) String jobGroup) {
    try {
      return quartzJobService.getScheduleJobStatus(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup:null);
    } catch (Exception e) {
      return "獲取狀態失敗";
    }
    //return "獲取狀態成功";
  }

}

測試
http://localhost:8080/api/quartz/startSimpleJob

到此這篇關於Springboot2.x+Quartz分散式叢集的實現的文章就介紹到這了,更多相關Springboot2.x Quartz分散式叢集內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!