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

news2024/11/16 7:33:44
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;

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Android+物联网】Android封装MQTT连接阿里云物联网平台

前言&#xff1a; 亲测可行&#xff0c;本文实现Android封装MQTT连接阿里云物联网平台。将MQTT协议和连接阿里云平台的操作通过Android studio写入APP中&#xff0c;并简单设计UI。实现手机APP远程控制单片机LED灯亮灭的功能。 关于《Android软件开发》&#xff0c;见如下专栏…

Unity填坑-灯光烘焙相关

Unity填坑-灯光烘焙相关 文章目录 Unity填坑-灯光烘焙相关前言一、Light的模式二、光的效果分类三、各种Light模式与烘焙的说明1.Realtime,实时光2.baked,烘焙光3.mixed,混合 四、实时全局光五、其他说明1.动态物体的全局光照效果2.手机使用烘焙注意的点3.其他设置 前言 项目组…

gem5学习(12):理解gem5 统计信息和输出——Understanding gem5 statistics and output

目录 一、config.ini 二、config.json 三、stats.txt 官方教程&#xff1a;gem5: Understanding gem5 statistics and output 在运行 gem5 之后&#xff0c;除了仿真脚本打印的仿真信息外&#xff0c;还会在根目录中名为 m5out 的目录中生成三个文件&#xff1a; config.i…

Mr_HJ / form-generator项目学习-增加自定义的超融组件(二)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

【pwn】cmcc_simplerop --rop链的构造

程序保护情况检查 32位程序&#xff0c;堆栈不可执行 主函数&#xff1a; 左边又是一堆函数&#xff0c;file看一下 发现是静态链接&#xff0c;那ret2libc不用考虑了&#xff0c;接着看一下有没有int 80 那可以考虑利用rop链调用execve函数&#xff0c;用系统调用的函数参数是…

Matlab 字符识别OCR实验

Matlab 字符识别实验 图像来源于屏幕截图&#xff0c;要求黑底白字。数据来源是任意二进制文件&#xff0c;内容以16进制打印输出&#xff0c;0-9a-f’字符被16个可打印字符替代&#xff0c;这些替代字符经过挑选&#xff0c;使其相对容易被识别。 第一步进行线分割和字符分割…

【动态规划】dp多状态问题

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;按摩师&#x1f449;&…

C语言操作符详解与进制

目录 一&#xff1a;操作符的分类 二&#xff1a;二进制和进制转换 2.1 2进制转10进制 2.1.1 10进制转2进制数字 2.2 2进制转8进制和16进制 2.2.1 2进制转8进制 2.2.2 2进制转16进制 三&#xff1a; 原码、反码、补码 四&#xff1a;移位操作符 4.1左移操作符 4.2 右…

Mini Event 抢先看!本周六共聚香港,展望 2024 波卡新机遇

2023 冬季波卡黑客松已经进入最终阶段&#xff0c;火热的开发实战比赛之旅以外&#xff0c;我们还为所有 Web3er 准备了一场精彩纷呈的「年终盛会」。来自区块链各领域的技术大咖、行业领军人、亚马逊云科技专家等一线大咖将共聚香港&#xff0c;参与本届黑客松的 Mini Event 活…

MES系统如何进行产品的质量管理

质量管理重点是对产品的检验&#xff0c;这里面包括&#xff1a;采购来料检验、工序检验、入库前检验等几个检验环节&#xff0c;并根据系统设定的检验标准进行检验&#xff0c;检验不通过的不能留到下个环节。质量管理也是万界星空科技云MES中的一个重要组成部分&#xff0c;旨…

认识kafka

认识KafKa 1.什么是KafKa&#xff1a; kafka是一种高吞吐量的分布式发布订阅消息消息队列&#xff0c;有如下特性&#xff1a; 可扩展性&#xff1a;Kafka可以处理大规模的数据流&#xff0c;并支持高并发的生产和消费操作。它可以水平扩展以适应负载的增长。 持久性&#x…

从无到有制作docker镜像、容器详细步骤

1、编写一个Dockerfile文件&#xff0c;内容如下 # 基础镜像jdk,jdk里包含里操作系统 FROM openjdk:8u282-jdk# 工作目录&#xff0c;也就是容器里目录 WORKDIR /home/prq/# 添加ppp目录下的文件到容器/home/prq/里 ADD ./ppp /home/prq/# 暴露端口8080 EXPOSE 8080# 启动脚本…

AdaM: An Adaptive Fine-Grained Scheme for Distributed Metadata Management——泛读论文

ICPP 2019 Paper 分布式元数据论文汇总 问题 为了同时解决元数据局部性和元数据服务器的负载均衡。 现有方法缺陷 基于哈希的方法&#xff1a;zFS [16]&#xff0c;CalvinFS [21]&#xff0c;DROP [24]&#xff0c;AngleCut [8] 静态子树划分&#xff1a;HDFS [6], NFS [14…

【Golang】IEEE754标准二进制字符串转为浮点类型

IEEE754介绍 IEEE 754是一种标准&#xff0c;用于表示和执行浮点数运算的方法。在这个标准中&#xff0c;单精度浮点数使用32位二进制表示&#xff0c;分为三个部分&#xff1a;符号位、指数位和尾数位。 符号位(s)用一个位来表示数的正负&#xff0c;0表示正数&#xff0c;1表…

LInux初学之路linux的磁盘分区/远程控制/以及关闭图形界面/查看个人身份

虚拟机磁盘分配 hostname -I 查看ip地址 ssh root虚拟就ip 远程连接 win10之后才有 远程控制重新启动 reboot xshell 使用&#xff08;个人和家庭版 免费去官方下载&#xff09; init 3 关闭界面 减小内存使用空间 init 5 回复图形界面 runlevel显示的是状态 此时和上…

代码随想录二刷 |二叉树 | 二叉搜索树的最小绝对差

代码随想录二刷 &#xff5c;二叉树 &#xff5c; 二叉搜索树的最小绝对差 题目描述解题思路 & 代码实现递归法迭代法 题目描述 530.二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树&#xff0c;请你计算树中任意两节点的差的绝对值的最小值。 示例&#…

VR全景技术如何应用在城市发展,助力城市宣传展示

引言&#xff1a; 随着科技的不断发展&#xff0c;VR全景技术正逐渐渗透到各行各业&#xff0c;其中较为广泛的应用之一便是城市展示。那么VR全景技术如何运用在城市展示领域&#xff0c;这项技术给城市发展带来了哪些好处&#xff1f; 一. VR全景技术简介 1.什么是VR全景技术…

Java十大经典算法——贪心算法

算法概念&#xff1a; 贪婪算法(贪心算法)是指在对问题进行求解时&#xff0c;在每一步选择中都采取最好或者最优(即最有利)的选择&#xff0c;从而希望能够导致结果是最好或者最优的算法&#xff1b;贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解)&#xff0c;但…

拯救者y9000p安装linux、windows双系统。

首先需要准备启动盘 我用的是Win32DiskImager来做的。资源使用的是ubuntu-20.04.6-desktop-amd64.iso。别用低版本&#xff0c;失败很多次之后的教训。 磁盘管理-磁盘分区-右键-压缩卷 这边分区出来之后&#xff0c;不要分配。安装时候会自动分配的。 重启之后F2进去BIOS设置…

计算机系统(软考版)----计算机系统基础知识、基本单位与进制(1)

文章目录 计算机系统基础知识一 硬件组成二 CPU功能三 CPU组成运算器控制器寄存器组 练习题&#xff08;答案为加粗部分&#xff09; 计算机基本单位与进制一 计算机基本单位二 进制1 概述2 进制转换3 进制加减 练习题&#xff08;答案为加粗部分&#xff09; 计算机系统基础知…