【QUARTZ】springboot+quartz动态配置定时任务

Quartz 介绍

   Quartz 定时任务可分为Trigger(触发器)Job(任务)Scheduler(调度器),定时任务的逻辑大体为:创建触发器和任务,并将其加入到调度器中,如下图所示:

Trigger 有五种触发器:        

        SimpleTrigger 触发器:需要在特定的日期/时间启动,且以指定的间隔时间(单位毫秒)重复执行 n 次任务,如 :在 9:00 开始,每隔1小时,每隔几分钟,每隔几秒钟执行一次 。没办法指定每隔一个月执行一次(每月的时间间隔不是固定值)。
        CalendarIntervalTrigger 触发器:指定从某一个时间开始,以一定的时间间隔(单位有秒,分钟,小时,天,月,年,星期)执行的任务。
        DailyTimeIntervalTrigger 触发器:指定每天的某个时间段内,以一定的时间间隔执行任务。并且支持指定星期。如:指定每天 9:00 至 18:00 ,每隔 70 秒执行一次,并且只要周一至周五执行。
        CronTrigger 触发器:基于日历的任务调度器,即指定星期、日期的某时间执行任务。
        NthIncludedDayTrigger 触发器:不同时间间隔的第 n 天执行任务。比如,在每个月的第 15 日处理财务发票记帐,同样设定双休日或者假期。

引入quartz依赖

<!--定时器-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

TaskScheduler类:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;

@Data
public class TaskScheduler {

    private String jobName;

    private String jobGroupName;

    private String state;

    private String jobClass;

    private String intervalUnit;

    private String intervalUnitName;

    private Integer timeInterval;

    private String cronExpression;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date startTime;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date endTime;

    private String description;
}

JobQuery类(查询用):

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class JobQuery {

    @ApiModelProperty(value = "模糊查询任务描述")
    private String jobNameLike;

}
TaskSchedulerController类:
import com.example.demo.system.domain.Result;
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import com.example.demo.system.service.ITaskSchedulerService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;


@RestController
@Api(value = "system/taskScheduler", tags = "定时任务")
@RequestMapping("taskScheduler")
public class TaskSchedulerController {

    @Resource
    private ITaskSchedulerService schedulerService;

    /**
     * 添加定时任务信息
     *
     * @param taskScheduler 定时任务信息
     * @return ReturnModel 添加定时任务
     */
    @PostMapping(value = "save")
    public Result<String> save(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName":"bookTask2",
//                "description":"书籍定时任务",
//                "jobTypeRadio":"expression",
//                "startTime":"2024-01-12 15:20:00",
//                "endTime":"2024-01-13 00:00:00",
//                "jobClass":"com.example.demo.system.controller.BookTask",
//                "cronExpression":"*/30 * * * * ?"
//        }
        schedulerService.save(taskScheduler);
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 移除定时任务
     *
     * @param taskScheduler 定时任务信息
     * @return ReturnModel 移除定时任务
     */
    @PostMapping(value = "/delete")
    public Result<String> delete(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName": "bookTask"
//        }
        schedulerService.delete(taskScheduler.getJobName());
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 修改定时任务
     *
     * @param taskScheduler 定时任务信息
     * @return ReturnModel 修改定时任务
     */
    @PostMapping(value = "update")
    public Result<String> update(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName":"bookTask",
//                "description":"1",
//                "jobTypeRadio":"expression",
//                "startTime":"2024-01-13 14:00:00",
//                "endTime":"",
//                "jobClass":"com.example.demo.system.controller.BookTask",
//                "cronExpression":"*/30 * * * * ?"
//        }
        schedulerService.update(taskScheduler);
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 暂停定时任务
     *
     * @param taskScheduler 定时任务名称
     * @return ReturnModel 暂停定时任务
     */
    @PostMapping(value = "pause")
    public Result<String> pause(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName": "bookTask2"
//        }
        schedulerService.pause(taskScheduler.getJobName());
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 恢复定时任务
     *
     * @param taskScheduler 定时任务名称
     * @return ReturnModel 恢复定时任务
     */
    @PostMapping(value = "resume")
    public Result<String> resume(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName": "bookTask2"
//        }
        schedulerService.resume(taskScheduler.getJobName());
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 执行定时任务
     *
     * @param taskScheduler 定时任务名称
     * @return ReturnModel 执行定时任务
     */
    @PostMapping(value = "executeJob")
    public Result<String> executeJob(@RequestBody TaskScheduler taskScheduler) {
//        {
//            "jobName": "bookTask2"
//        }
        schedulerService.executeJob(taskScheduler.getJobName());
        return Result.success(taskScheduler.getJobName());
    }

    /**
     * 查询单个定时任务信息
     *
     * @param jobName 任务名称
     * @return ReturnModel 查询单个定时任务信息
     */
    @GetMapping(value = "selectByName")
    public Result<TaskScheduler> selectByName(@RequestParam("jobName") String jobName) {
        TaskScheduler taskScheduler = schedulerService.selectByName(jobName);
        return Result.success(taskScheduler);
    }

    /**
     * 查询定时任务列表
     *
     * @param jobQuery 查询条件
     * @return ReturnModel 查询定时任务列表
     */
    @PostMapping(value = "selectList")
    public Result<List<TaskScheduler>> selectList(@RequestBody JobQuery jobQuery) {
//        {
//            "jobNameLike": ""
//        }
        List<TaskScheduler> taskSchedulers = schedulerService.selectList(jobQuery);
        return Result.success(taskSchedulers);
    }
}

ITaskSchedulerService接口:
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import java.util.List;

public interface ITaskSchedulerService {


    /**
     * 添加定时任务信息
     *
     * @param taskScheduler 定时任务信息
     */
    void save(TaskScheduler taskScheduler);

    /**
     * 移除定时任务--根据任务名称移除
     *
     * @param jobName 任务名
     */
    void delete(String jobName);

    /**
     * 移除定时任务
     *
     * @param groupName 组名
     * @param jobName   任务名
     */
    void delete(String jobName, String groupName);

    /**
     * 修改定时任务
     *
     * @param taskScheduler 任务信息
     */
    void update(TaskScheduler taskScheduler);

    /**
     * 添加任务
     *
     * @param jobName 任务名
     * @return 任务信息
     */
    TaskScheduler selectByName(String jobName);

    /**
     * 查询单个定时任务信息
     *
     * @param groupName 组名称
     * @param jobName   任务名称
     * @return 查询结果
     */
    TaskScheduler selectByName(String jobName, String groupName);


    /**
     * 查询定时任务列表
     *
     * @param jobQuery 查询条件
     * @return 查询结果
     */
    List<TaskScheduler> selectList(JobQuery jobQuery);

    /**
     * 暂停定时任务
     *
     * @param jobName 任务名
     */
    void pause(String jobName);

    /**
     * 暂停定时任务
     *
     * @param jobName   任务名
     * @param groupName 组名
     */
    void pause(String jobName, String groupName);

    /**
     * 恢复定时任务
     *
     * @param jobName 任务名
     */
    void resume(String jobName);

    /**
     * 恢复定时任务
     *
     * @param jobName   任务名
     * @param groupName 组名
     */
    void resume(String jobName, String groupName);

    /**
     * 执行定时任务
     *
     * @param jobName 任务名
     */
    void executeJob(String jobName);

    /**
     * 执行定时任务
     *
     * @param jobName   任务名
     * @param groupName 组名
     */
    void executeJob(String jobName, String groupName);
}

TaskSchedulerServiceImpl实现类:
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.example.demo.system.job.JobQuery;
import com.example.demo.system.job.TaskScheduler;
import com.example.demo.system.service.ITaskSchedulerService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CalendarIntervalTriggerImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;


@Service
@Slf4j
public class TaskSchedulerServiceImpl implements ITaskSchedulerService {


    @Resource
    private Scheduler scheduler;

    @Override
    @SneakyThrows
    public void save(TaskScheduler taskScheduler) {
        Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(taskScheduler.getJobClass());
        String jobName = taskScheduler.getJobName();
        String jobGroupName = StrUtil.isEmpty(taskScheduler.getJobGroupName()) ? Scheduler.DEFAULT_GROUP : taskScheduler.getJobGroupName();
        String triggerGroupName = StrUtil.isEmpty(taskScheduler.getJobGroupName()) ? Scheduler.DEFAULT_GROUP : taskScheduler.getJobGroupName();
        Date startTime = taskScheduler.getStartTime() == null ? new Date() : taskScheduler.getStartTime();
        Date endTime = taskScheduler.getEndTime();
        String description = StrUtil.isEmpty(taskScheduler.getDescription()) ? "" : taskScheduler.getDescription();

        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).withDescription(description).build();
        if (taskScheduler.getCronExpression() != null && taskScheduler.getCronExpression().length() > 0) {
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobName, triggerGroupName)
                    .startAt(startTime)
                    .endAt(endTime)
                    .withSchedule(CronScheduleBuilder.cronSchedule(taskScheduler.getCronExpression()).withMisfireHandlingInstructionDoNothing())
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
        } else {
            DateBuilder.IntervalUnit cycleUnit = DateBuilder.IntervalUnit.valueOf(taskScheduler.getIntervalUnit());
            Integer timeInterval = taskScheduler.getTimeInterval();
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobName, triggerGroupName)
                    .startAt(startTime)
                    .endAt(endTime)
                    .withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withInterval(timeInterval, cycleUnit).withMisfireHandlingInstructionDoNothing())
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
        }
    }

    /**
     * 移除定时任务--根据任务名称移除
     */
    @Override
    public void delete(String jobName) {
        delete(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 移除定时任务
     */
    @Override
    @SneakyThrows
    public void delete(String jobName, String groupName) {
        groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;

        JobKey jobKey = new JobKey(jobName, groupName);
        TriggerKey triggerKey = new TriggerKey(jobName, groupName);
        scheduler.pauseTrigger(triggerKey);
        scheduler.pauseJob(jobKey);
        // 移除触发器
        scheduler.unscheduleJob(triggerKey);
        // 删除任务
        scheduler.deleteJob(jobKey);

    }

    /**
     * 修改定时任务
     */
    @Override
    @SneakyThrows
    public void update(TaskScheduler taskScheduler) {
        delete(taskScheduler.getJobName());
        save(taskScheduler);
    }

    /**
     * 查询单个定时任务
     */
    @Override
    @SneakyThrows
    public TaskScheduler selectByName(String jobName, String groupName) {
        groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
        TaskScheduler taskScheduler = new TaskScheduler();
        JobKey jobKey = new JobKey(jobName, groupName);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        taskScheduler.setJobName(jobName);
        taskScheduler.setJobGroupName(groupName);
        setJob(jobKey, taskScheduler, jobDetail);

        return taskScheduler;
    }

    /**
     * 查询单个定时任务
     */
    @Override
    public TaskScheduler selectByName(String jobName) {
        return selectByName(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 查询定时任务列表
     */
    @Override
    @SneakyThrows
    public List<TaskScheduler> selectList(JobQuery jobQuery) {
        List<TaskScheduler> taskSchedulers = new ArrayList<>();
        GroupMatcher<JobKey> mathcher = GroupMatcher.anyJobGroup();
        String keyWord = jobQuery.getJobNameLike();
        Set<JobKey> jobKeys = scheduler.getJobKeys(mathcher);
        if (CollUtil.isEmpty(jobKeys)) {
            return new ArrayList<>();
        }
        for (JobKey jobKey : jobKeys) {
            if (StrUtil.isNotEmpty(keyWord) && !jobKey.getName().contains(keyWord)) {
                continue;
            }
            TaskScheduler taskScheduler = new TaskScheduler();
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            taskScheduler.setJobName(jobKey.getName());
            taskScheduler.setJobGroupName(jobKey.getGroup());
            List<? extends Trigger> triggers = setJob(jobKey, taskScheduler, jobDetail);
            taskScheduler.setState(scheduler.getTriggerState(triggers.get(0).getKey()).name());
            taskSchedulers.add(taskScheduler);
        }
        return taskSchedulers;
    }

    private List<? extends Trigger> setJob(JobKey jobKey, TaskScheduler taskScheduler, JobDetail jobDetail) throws SchedulerException {
        taskScheduler.setJobClass(jobDetail.getJobClass().getName());
        taskScheduler.setDescription(jobDetail.getDescription());
        List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
        Trigger trigger = triggers.get(0);
        taskScheduler.setStartTime(trigger.getStartTime());
        taskScheduler.setEndTime(trigger.getEndTime());
        if (trigger.getClass().equals(CronTriggerImpl.class)) {
            CronTriggerImpl cronTriggerImpl = (CronTriggerImpl) trigger;
            taskScheduler.setCronExpression(cronTriggerImpl.getCronExpression());
        }
        if (trigger.getClass().equals(CalendarIntervalTriggerImpl.class)) {
            CalendarIntervalTriggerImpl calendarIntervalTriggerImpl = (CalendarIntervalTriggerImpl) trigger;
            taskScheduler.setIntervalUnit(calendarIntervalTriggerImpl.getRepeatIntervalUnit().toString());
            taskScheduler.setTimeInterval(calendarIntervalTriggerImpl.getRepeatInterval());
        }
        return triggers;
    }

    /**
     * 暂停定时任务
     */
    @Override
    public void pause(String jobName) {
        pause(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 暂停定时任务
     */
    @Override
    @SneakyThrows
    public void pause(String jobName, String groupName) {
        groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
        TriggerKey triggerKey = new TriggerKey(jobName, groupName);
        scheduler.pauseTrigger(triggerKey);
        JobKey jobKey = new JobKey(jobName);
        scheduler.pauseJob(jobKey);

    }

    /**
     * 恢复定时任务
     */
    @Override
    public void resume(String jobName) {
        resume(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 恢复定时任务
     */
    @Override
    @SneakyThrows
    public void resume(String jobName, String groupName) {
        groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;

        TriggerKey triggerKey = new TriggerKey(jobName, groupName);
        scheduler.resumeTrigger(triggerKey);
        JobKey jobKey = new JobKey(jobName);
        scheduler.resumeJob(jobKey);

    }

    /**
     * 执行定时任务
     */
    @Override
    public void executeJob(String jobName) {
        executeJob(jobName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 执行定时任务
     */
    @Override
    @SneakyThrows
    public void executeJob(String jobName, String groupName) {
        groupName = StrUtil.isEmpty(groupName) ? Scheduler.DEFAULT_GROUP : groupName;
        JobKey jobKey = new JobKey(jobName, groupName);
        scheduler.triggerJob(jobKey);
    }
}

定时任务业务逻辑类BookTask:

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;


@Slf4j
public class BookTask extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("book定时任务-开始执行:{}", DateUtil.date().toString("yyyy-MM-dd HH:mm:ss"));
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("book定时任务-执行结束:{}", DateUtil.date().toString("yyyy-MM-dd HH:mm:ss"));

    }
}

以上动态配置定时任务需要的东西准备完毕,下一步就是配置

在此用swaggger来做测试

1、保存定时任务,我在此保存了两次  bookTask和bookTask2

注意:如果传了开始时间-startTime和结束时间-endTime,开始时间一定要小于结束时间,且开始时间要是一个未来时间,否则永远不会生效,也可以只传开始时间传结束时间。

2、看看列表

3、查看具体信息

4、更新定时任务:

5、删除定时任务

6、执行一次定时任务

7、暂停定时任务

8、恢复定时任务

9、持久化:在配置文件中加上该配置并新建数据表即可,重启项目后,配置的定时任务还在

spring:
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: embedded
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,  
JOB_NAME VARCHAR(200) NOT NULL,  
JOB_GROUP VARCHAR(200) NOT NULL,  
DESCRIPTION VARCHAR(250) NULL,  
JOB_CLASS_NAME VARCHAR(250) NOT NULL,  
IS_DURABLE VARCHAR(1) NOT NULL,  
IS_NONCONCURRENT VARCHAR(1) NOT NULL,  
IS_UPDATE_DATA VARCHAR(1) NOT NULL,  
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,  
JOB_DATA BLOB NULL,  
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
JOB_NAME VARCHAR(200) NOT NULL,  
JOB_GROUP VARCHAR(200) NOT NULL,  
DESCRIPTION VARCHAR(250) NULL,  
NEXT_FIRE_TIME BIGINT(13) NULL,  
PREV_FIRE_TIME BIGINT(13) NULL,  
PRIORITY INTEGER NULL,  
TRIGGER_STATE VARCHAR(16) NOT NULL,  
TRIGGER_TYPE VARCHAR(8) NOT NULL,  
START_TIME BIGINT(13) NOT NULL,  
END_TIME BIGINT(13) NULL,  
CALENDAR_NAME VARCHAR(200) NULL,  
MISFIRE_INSTR SMALLINT(2) NULL,  
JOB_DATA BLOB NULL,  
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))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
REPEAT_COUNT BIGINT(7) NOT NULL,  
REPEAT_INTERVAL BIGINT(12) NOT NULL,  
TIMES_TRIGGERED BIGINT(10) NOT NULL,  
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))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_CRON_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
CRON_EXPRESSION VARCHAR(120) NOT NULL,  
TIME_ZONE_ID VARCHAR(80),  
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))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SIMPROP_TRIGGERS  
  (
    SCHED_NAME VARCHAR(120) NOT NULL,  
    TRIGGER_NAME VARCHAR(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR(200) NOT NULL,  
    STR_PROP_1 VARCHAR(512) NULL,  
    STR_PROP_2 VARCHAR(512) NULL,  
    STR_PROP_3 VARCHAR(512) NULL,  
    INT_PROP_1 INT NULL,  
    INT_PROP_2 INT NULL,  
    LONG_PROP_1 BIGINT NULL,  
    LONG_PROP_2 BIGINT NULL,  
    DEC_PROP_1 NUMERIC(13,4) NULL,  
    DEC_PROP_2 NUMERIC(13,4) NULL,  
    BOOL_PROP_1 VARCHAR(1) NULL,  
    BOOL_PROP_2 VARCHAR(1) NULL,  
    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))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_BLOB_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
BLOB_DATA BLOB NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),  
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_CALENDARS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
CALENDAR_NAME VARCHAR(200) NOT NULL,  
CALENDAR BLOB NOT NULL,  
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_FIRED_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
ENTRY_ID VARCHAR(95) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
INSTANCE_NAME VARCHAR(200) NOT NULL,  
FIRED_TIME BIGINT(13) NOT NULL,  
SCHED_TIME BIGINT(13) NOT NULL,  
PRIORITY INTEGER NOT NULL,  
STATE VARCHAR(16) NOT NULL,  
JOB_NAME VARCHAR(200) NULL,  
JOB_GROUP VARCHAR(200) NULL,  
IS_NONCONCURRENT VARCHAR(1) NULL,  
REQUESTS_RECOVERY VARCHAR(1) NULL,  
PRIMARY KEY (SCHED_NAME,ENTRY_ID))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SCHEDULER_STATE (  
SCHED_NAME VARCHAR(120) NOT NULL,  
INSTANCE_NAME VARCHAR(200) NOT NULL,  
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,  
CHECKIN_INTERVAL BIGINT(13) NOT NULL,  
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_LOCKS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
LOCK_NAME VARCHAR(40) NOT NULL,  
PRIMARY KEY (SCHED_NAME,LOCK_NAME))  
ENGINE=InnoDB;  
  
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);  
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);  
  
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);  
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);  
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);  
  
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);  
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);  
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);  
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);  
  
commit;

注意:如果有其他业务逻辑 ,需要在对应的方法里加业务代码

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【服务器】服务器管理 - cockpit开启

开启cockpit #!/bin/bashsed -i s/is():where()/is(*):where(*)/ /usr/share/cockpit/static/login.jssystemctl enable --now cockpit.socket #开启cockpit服务systemctl start cockpit.socket 登录 https://ip:9090

03.分支结构

分支结构 应用场景 迄今为止&#xff0c;我们写的Python代码都是一条一条语句顺序执行&#xff0c;这种代码结构通常称之为顺序结构。然而仅有顺序结构并不能解决所有的问题&#xff0c;比如我们设计一个游戏&#xff0c;游戏第一关的通关条件是玩家获得1000分&#xff0c;那…

uniapp-uniCloud的基本使用(编写云存储的地区级联选择器)

目录 新建项目&#xff0c;创建 uniCloud 服务空间并关联 1. 新建项目 2. 创建 uniCloud 服务空间并关联 manifest.json内未配置Appld,请重新获取后再 云数据库的使用 城市选择和云数据库 介绍 云端数据 DB Schema概述 新建项目&#xff0c;创建 uniCloud 服务空间并关…

【机器学习300问】4、机器学习到底在学习什么?

首先我们先了解一个前置问题&#xff0c;再回答机器学习到底在学习什么。 一、求机器学习问题有哪几步&#xff1f; 求解机器学习问题的步骤可以分为“学习”和“推理”两个阶段。首先&#xff0c;在学习阶段进行模型的学习&#xff0c;然后&#xff0c;在推理阶段用学到的模型…

实现秒杀功能设计

页面 登录页面 登录成功后&#xff0c;跳转商品列表 商品列表页 加载商品信息 商品详情页 根据商品id查出商品信息返回VO&#xff08;包括rmiaoshaStatus、emainSeconds&#xff09;前端根据数据展示秒杀按钮&#xff0c;点击开始秒杀 订单详情页 秒杀页面设置 后端返回秒杀…

1.12 力扣中等图论

797. 所有可能的路径 - 力扣&#xff08;LeetCode&#xff09; 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节…

Window Docker安装

1.下载安装Docker 在Windows上安装Docker桌面_Docker中文网 (dockerdocs.cn)https://dockerdocs.cn/docker-for-windows/install/index.html2.安装完&#xff0c;修改镜像 Docker——Windows版本Docker安装_docker windows-CSDN博客https://blog.csdn.net/weixin_51351637/ar…

基于Linux的Flappy bird游戏开发

项目介绍 主要是使用C语言实现&#xff0c;开启C项目之旅。 复习巩固C语言、培养做项目的思维。 功能&#xff1a; 按下空格键小鸟上升&#xff0c;不按下落&#xff1b; 显示小鸟需要穿过的管道&#xff1b; 小鸟自动向右飞行&#xff1b;&#xff08;管道自动左移和创建&a…

训练营第四十二天 | 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

01背包问题 二维 代码随想录 dp二维数组 优化 01背包问题 一维 代码随想录 dp一维数组 416. 分割等和子集 把数组分成总和相等的两份&#xff0c;如果数组总和为奇数&#xff0c;不能分割&#xff0c;若有符合的数组子集&#xff0c;返回true 代码随想录 class Solution {p…

Java内存模型之原子性

文章目录 1.什么是原子性2.Java中的原子操作有哪些3.long和double的原子性4.原子操作 原子操作 ! 原子操作 1.什么是原子性 一系列的操作&#xff0c;要么全部执行成功&#xff0c;要么全部不执行&#xff0c;不会出现执行一半的情况&#xff0c;是不可分割的。 注意&#x…

Android perfetto memory开源工具分析

目录 原理 官网链接 下载heap_profile producer_support.cc 本地编译 push heapprofd 工具使用 pb文件获取 打开*.pb文件 trace文件 提高系统CPU性能 拆解特定函数内存占用 环境配置 工具使用 修改heap_profile 脚本 原理 Android perfetto memory分析工具和ma…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(2)

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#xff08;2&#xff09; 在 https://zhangphil.blog.csdn.net/article/details/135374279 基础上&#xff0c;增加一个功能&#xff0c;当手指在上面的图片…

如何使用SVN查看旧版本

和目录 第一步&#xff1a;打开SVN客户端 第二步&#xff1a;浏览历史版本 第三步&#xff1a;还原历史版本 结论 Subversion (缩写为SVN)是一种常用的版本控制系统&#xff0c;它可以帮助团队协作开发软件项目。除了基本的版本控制功能外&#xff0c;SVN还提供了许多其他功…

【已解决】如何用递归实现位运算计算两数之和

本博文源于笔者正在思考的如何用递归进行计算两数之和。读者一般都会想到用while循环进行操作&#xff0c;位运算两数之和的思想就犹如辗转相除法。文章并附加了对这个方法的流程演示 问题来源 想要用递归实现两数之和。 代码实现 #include<stdio.h> int add(int num…

(十)IIC总线-PCF8591-ADC/DAC

文章目录 IIC总线篇起始&#xff0c;终止信号应答信号发送&#xff0c;读取数据IIC通讯规则 PCF8591-ADC-DAC篇特性一般说明地址Control byte&#xff08;控制字&#xff09;简单了解一下DAC电阻分隔链应用为王DAC的应用如何设置DAC输出如何调用DAC功能 ADC的应用ADC采集特点AD…

【群晖NAS】记一次FRP报错:login to server failed: connection write timeout

报错如下&#xff1a; rongfuDS224plus:~/fff/frp$ ./frpc -c ./frpc.toml 2024/01/12 23:08:31 [I] [root.go:139] start frpc service for config file [./frpc.toml] 2024/01/12 23:08:41 [W] [service.go:131] login to server failed: i/o deadline reached 2024/01/12 2…

Java中的栈和队列操作,相互实现(力扣 232, 225)

栈和队列&#xff08;Java&#xff09; Java中的 栈 & 队列 操作栈的使用队列的使用 LeetCode 232. 用栈实现队列我的代码 LeetCode 225. 用队列实现栈我的代码 Java中的 栈 & 队列 操作 栈的使用 栈的方法功能Stack()构造一个空的栈E push(E e)将e入栈&#xff0c;并…

缓存学习实战篇

缓存练习题&#xff08;用户查询操作&#xff09; public List<ShopType> queryAllType() throws JsonProcessingException {//从缓存中查数据String shopTypeJson stringRedisTemplate.opsForValue().get("cache:shopType");//如果缓存命中&#xff0c;if (S…

基于stm32f4的蓝牙控制小车

1. 引言 蓝牙的创始人是瑞典爱立信公司&#xff0c;蓝牙技术是一种无限数据与语音通信的开放性全球规范&#xff0c;它以低成本的近距离无线连接为基础&#xff0c;为固定与移动设备通信环境建立一个特别连接。手机之间通过蓝牙实现数据共享成为常理&#xff0c;将手机变为遥…

【前后端的那些事】前后端环境搭建+树形结构表格实现

文章目录 1. 前后端项目环境搭建2. table-tree2.1 后端准备2.2 前端准备 前言&#xff1a;最近写项目&#xff0c;发现了一些很有意思的功能&#xff0c;想写文章&#xff0c;录视频把这些内容记录下。但这些功能太零碎&#xff0c;如果为每个功能都单独搭建一个项目&#xff0…