Follow wechat technical official account:CodingTechWorkLearn and progress together.

The introduction

When working with Scheduled tasks, the first thing that comes to mind is using the @scheduled annotation to set a time for a task to be Scheduled to execute. The @scheduled annotation isn’t going to cut it when there are too many Scheduled tasks, or when there are additions, deletions, changes, and reviews required. This article summarizes the use of the Quartz timing framework.

Quartz is introduced

An overview of the

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application – from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, Such as support for JTA Transactions and clustering. Quartz is freely usable, licensed under the Apache 2.0 license.

Quartz, a project of OpenSymphony, is an open source job scheduling framework written in Java.

The characteristics of

  1. Support distributed high availability. When we need a Scheduled task that can be executed on only one node of multiple nodes, we need Quartz to implement it. Otherwise, using methods such as @Scheduled will cause all nodes to be executed once.
  2. Support for persistence. Quartz has its own tables for persistence of scheduled tasks.
  3. Supports multi-task scheduling and management. Quartz can store multiple scheduled tasks in the database for job scheduling, and can realize the management of adding, deleting, modifying, and checking scheduled tasks.

composition

Quartz is made up of three parts:

  1. Task: JobDetail
  2. Triggers: Trigger (divided into SimpleTrigger and CronTrigger)
  3. Scheduler: Scheduler

JobDetail

JobDetail consists of JobKey (job name and group), JobClass, JobDataMap (task-related data), and JobBuilder. The first few are commonly used. JobDetail source

package org.quartz;

import java.io.Serializable;

public interface JobDetail extends Serializable.Cloneable {
    JobKey getKey(a);

    String getDescription(a);

    Class<? extends Job> getJobClass();

    JobDataMap getJobDataMap(a);

    boolean isDurable(a);

    boolean isPersistJobDataAfterExecution(a);

    boolean isConcurrentExectionDisallowed(a);

    boolean requestsRecovery(a);

    Object clone(a);

    JobBuilder getJobBuilder(a);
}
Copy the code

JobDetail sample

		Map<String,String> jobData = new HashMap<>();
		String jobName = "schedulerJob";
		String jobGroup = "schedulerGroup";
		jobData.put("key00"."value00");
        JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
                .withIdentity(jobName, jobGroup)
                .usingJobData("key01"."value01")
                .usingJobData(jobData)
                .storeDurably()
                .build();
Copy the code

Trigger

Trigger Specifies the Job implementation classes to be triggered. There are two main implementation classes: SimpleTrigger and CronTrigger. Trigger consists of the following parts:

  1. TriggerKey (Job name name and group)
  2. JobDataMap (Trigger related data, which stores the same key as JobDataMap in JobDetail, and overwrites the former if the value is different.)
  3. ScheduleBuilder (CronScheduleBuilder, SimpleScheduleBuilder, CalendarIntervalScheduleBuilder, DailyTimeIntervalScheduleBuil Der uses the first two.

The Trigger sample

	//SimpleScheduleBuilder
	String triggerName = "schedulerJob";
	String triggerGroup = "schedulerGroup";
	Trigger trigger = TriggerBuilder
	    .newTrigger()
	    .withIdentity(triggerName, triggerGroup)
	    .withSchedule(SimpleScheduleBuilder)
	    .repeatSecondlyForever(1)
	    .withIntervalInSeconds(0)
	    .withRepeatCount(0))
	    .startNow()
	    .build();
	
	//CronScheduleBuilder
	String triggerName2 = "schedulerJob2";
	String triggerGroup2 = "schedulerGroup2";
	String jobTime = "0 0 * * * ?";
	Trigger trigger2 = TriggerBuilder
		.newTrigger()
		.withIdentity(triggerName2, triggerGroup2)
		.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
		.withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
		.startNow()
		.build();
Copy the code

Scheduler

The scheduler reads the Trigger Trigger to Trigger the scheduled task JobDetail. SchedulerFactory can be used to create schedulers, including StdSchedulerFactory (common) and DirectSchedulerFactory.

  1. The StdSchedulerFactory uses a set of properties (placed in a configuration file) to create and initialize the scheduler and then passgetScheduler()Method to generate the scheduler.
  2. DirectSchedulerFactory is uncommon and easy to hard code.

The Scheduler sample

	/ / build jobDetail, the trigger. .//StdSchedulerFactory
	SchedulerFactory schedulerFactory = new StdSchedulerFactory();
	Scheduler schedulerStd = schedulerFactory.getScheduler();
	
	/ / DirectSchedulerFactory way
	DirectSchedulerFactory directSchedulerFactory = DirectSchedulerFactory.getInstance();
	Scheduler schedulerDir=directSchedulerFactory.getScheduler();
	
	// Perform scheduling
	schedulerStd.scheduleJob(jobDetail, trigger);
	schedulerStd.start();
Copy the code

Cron expression

A Cron expression is a string that can be expressed in two ways:

  1. Seconds minutes hours days months weeks years
  2. Seconds minutes hours days months weeks

The year is optional, so the general expression is 6-7 fields, separated by Spaces. The days of the week can be numbered as well as abbreviated1-7 NumbersTo represent, notice1Represents theSunday.7The saidSaturday.

  • *: asterisk (asterisk), indicating the time domain corresponding to each fieldeachIn the sun every day.
  • ?: question mark, which can only be used in the date and week fieldsMeaningless value, equivalent to the point character.
  • -: minus sign, indicating a range, as in minutes5-8 -, it means5 to 8 minutesThat is 5, 6, 7, 8 minutes.
  • .: comma, indicating a list value, as used in midweek Monday and WednesdayMON,WED, can also be expressed by numbers:1, 3.
  • /: slash, usex/yTo represent a sequence of equal step sizes, where x represents the starting value and y represents the step size. As in the second field0/15, which means that you start at 0 seconds and increase every 15 seconds, i.e. 0 seconds,15 seconds,30 seconds,45 secondsEvery 15 secondsPerform tasks.
  • L: can only be used in the date and week fields, indicatingLast. In the date,LThe last day of a month, e.g., the 31st of January. In the middle of the week,LRepresents Saturday (or the number 7).
  • W: Can be used only in the date field, indicating the latest working period. Such as10WIs the closest working day to the 10th of the month. If the 10th is a Saturday, Friday the 9th matches. If the 10th falls on a Sunday, it matches Monday the 11th. If 10 is Monday, it matches Monday 10.LWThe combination represents the last working day of the month.
  • C: can only be used in the date and week fields, indicatingCalendar, that is, the date to which the plan is associated. If the date is not associated, it is equivalent to associating all dates. As used in dates4CIs the first day after date 4. Midweek use1C, the day after Sunday.
  • #: Hash marks can only be used in the week field to indicate a working day of the month. Such as6 # 2Represents the second Friday of the month (where,6Friday,# 3Represents the second of the month).

Cron sample

Cron expression instructions
0 0 * * * ? Runs at 0 minutes 0 seconds per hour
0, 0, 1 * *? It runs at 01:00:00 every day
0, 0, 1 * *? * It runs at 01:00:00 every day. Ditto
0, 0, 1 * *? 2021 It will run at 01:00:00 every day in 2021
0 times 10 times * *, right? It runs every minute between 10:00 and 11:00 every day, starting at 10:00:00 and ending at 10:59:00
0 0/5, 10 * *, right? It runs every 5 minutes between 10:00 and 11:00 every day, starting at 10:00:00 and ending at 10:59:00
0 0/5 10,15 * * ? It runs every five minutes between 10:00 and 11:00 and every five minutes between 15:00 and 16:00 every day
0, 0, minus 10, 10 * *? It runs every minute between 10:00-10:10 every day
0 to 10 1? * MON-FRI Every Monday, Tuesday, Wednesday, Thursday and Friday at 1:10
0, 10, 1, 1 times? It runs at 1:10 on the first of each month
0 10 1 L * ? It runs at 1:10 p.m. on the last day of the month
0 to 10 1? * 6L Runs at 1:10 on the last Friday of every month
0 to 10 1? * 6 # 3 Runs every 3rd Friday of every month at 1:10

Quartz add delete change check template

QuartzService interface class

package com.andya.selfcode.quartzservice;

import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.List;
import java.util.Map;

/ * * *@author Andya
 * @date2021/4/01 * /
public interface QuartzService {

    /** * Add a task job *@paramJobClass Job implementation class *@paramJobName Job name (unique) *@paramJobGroupName Name of the job group *@paramJobTime Task interval (s) *@paramJobTimes Indicates the number of times a task is run (if <0, the number is unlimited) *@paramJobData Task parameter */
    void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                int jobTimes, Map jobData);

    /** * Add a task job *@paramJobClass Job implementation class *@paramJobName Job name (unique) *@paramJobGroupName Name of the job group *@paramJobTime Indicates the task time *@paramJobData Task parameter */
    void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData);

    /** * Modify a task job *@paramJobName Task name *@paramJobGroupName Task group name *@paramJobTime cron Indicates the time expression */
    void updateJob(String jobName, String jobGroupName, String jobTime);

    /** * Delete a job *@param jobName
     * @param jobGroupName
     */
    void deleteJob(String jobName, String jobGroupName);

    /** * Suspends a task job *@param jobName
     * @param jobGroupName
     */
    void pauseJob(String jobName, String jobGroupName);

    /** * Restore a job *@param jobName
     * @param jobGroupName
     */
    void resumeJob(String jobName, String jobGroupName);

    /** * Immediately executes a task job *@param jobName
     * @param jobGroupName
     */
    void runAJobNow(String jobName, String jobGroupName);

    /** * Get all jobs *@return* /
    List<Map<String, Object>> queryAllJob();

    /** * Get the running job *@return* /
    List<Map<String, Object>> queryRunJob();


}

Copy the code

QuartzServiceImpl implementation class

package com.andya.selfcode.quartz.service;

import com.andya.selfcode.quartz.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;

/ * * *@author Andya
 * @date2021/4/01 * /
@Slf4j
@Service
public class QuartzServiceImpl implements QuartzService {

    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void startScheduler(a) {
        try {
            scheduler.start();
        } catch(SchedulerException e) { e.printStackTrace(); }}/** * add a job **@paramJobClass * Task implementation class *@paramJobName * Task name *@paramJobGroupName * Task group name *@paramJobTime * Time expression (this is how many seconds a task is every) *@paramJobTimes * Number of runs (<0: unlimited) *@paramJobData * Parameter */
    @Override
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                       int jobTimes, Map jobData) {
        try {
            // The task name and group form the task key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // Set job parameters
            if(jobData! =null && jobData.size()>0){
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // Use the simpleTrigger rule
            Trigger trigger = null;
            if (jobTimes < 0) {
                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
                        .startNow().build();
            } else {
                trigger = TriggerBuilder
                        .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
                                .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
                        .startNow().build();
            }
            log.info("jobDataMap: {}", jobDetail.getJobDataMap().getWrappedMap());
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("add job error!"); }}/** * add a job **@paramJobClass * Task implementation class *@paramJobName * Task name (unique recommended) *@paramJobGroupName * Task group name *@paramJobTime * time expression (e.g. 0/5 * * * *?) *@paramJobData * Parameter */
    @Override
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData) {
        try {
            // Create jobDetail instance and bind the Job implementation class
            // Specify the name of the job, the name of the group to which it belongs, and the binding of the job class
            // The task name and group form the task key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // Set job parameters
            if(jobData! =null && jobData.size()>0){
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // Define scheduling trigger rules
            // Use cornTrigger rules
            // Trigger key
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();
            // Register jobs and triggers with the task scheduler
            scheduler.scheduleJob(jobDetail, trigger);
            log.info("jobDataMap: {}", jobDetail.getJobDataMap());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("add job error!"); }}/** * Change the time expression of a job **@param jobName
     * @param jobGroupName
     * @param jobTime
     */
    @Override
    public void updateJob(String jobName, String jobGroupName, String jobTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            log.info("new jobTime: {}", jobTime);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            // Restart the trigger
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("update job error!"); }}/** * Delete a job **@paramJobName * Task name *@paramJobGroupName * Task group name */
    @Override
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            scheduler.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("delete job error!"); }}/** * Suspends a job **@param jobName
     * @param jobGroupName
     */
    @Override
    public void pauseJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("pause job error!"); }}/** * Restore a job **@param jobName
     * @param jobGroupName
     */
    @Override
    public void resumeJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("resume job error!"); }}/** * Execute a job ** immediately@param jobName
     * @param jobGroupName
     */
    @Override
    public void runAJobNow(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("run a job error!"); }}/** * Get the list of all planned tasks **@return* /
    @Override
    public List<Map<String, Object>> queryAllJob() {
        List<Map<String, Object>> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            jobList = new ArrayList<Map<String, Object>>();
            for (JobKey jobKey : jobKeys) {
                log.info("maps: {}", scheduler.getJobDetail(jobKey).getJobDataMap().getWrappedMap());
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description"."Trigger :" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression); } jobList.add(map); }}}catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("query all jobs error!");
        }
        return jobList;
    }

    /** * get all running jobs **@return* /
    @Override
    public List<Map<String, Object>> queryRunJob() {
        List<Map<String, Object>> jobList = null;
        try {
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                Map<String, Object> map = new HashMap<String, Object>();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                map.put("jobName", jobKey.getName());
                map.put("jobGroupName", jobKey.getGroup());
                map.put("description"."Trigger :" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                map.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    map.put("jobTime", cronExpression); } jobList.add(map); }}catch (SchedulerException e) {
            e.printStackTrace();
            throw new BaseException("query run jobs error!");
        }
        returnjobList; }}Copy the code

Quartz usage

Automatically called when the application starts

Write a configuration class that is instantiated using the @bean annotation.

QuartzConfig configuration class

package com.andya.selfcode.quartz;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

/ * * *@author Andya
 * @create2021/04/01 * /
@Configuration
@Service
public class QuartzConfig {

    @Bean
    public JobDetail scheduleJobDetail(a) {
        System.out.println("**************************************** scheduler job begin");
        JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
                .withIdentity("schedulerJob")
                .storeDurably()
                .build();
        System.out.println("**************************************** scheduler job end");
        return jobDetail;
    }

    @Bean
    public Trigger scheduleJobDetailTrigger(a) {
        Trigger trigger = TriggerBuilder
                .newTrigger()
                .forJob(scheduleJobDetail())
                .withIdentity("schedulerJob")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
                .startNow()
                .build();
        System.out.println("schedulerJob trigger end");
        return trigger;
    }
Copy the code

SchedulerJob Adds or deletes tasks

package com.andya.selfcode.quartz;

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;

/ * * *@author Andya
 * @create2021/04/01 * /
@Slf4j
public class SchedulerJob extends QuartzJobBean {

    @Autowired
    QuartzService quartzService;

    @Value("${schedule.cron.withJob1}")
    private String cronTimeJob1;

    public String getCronTimeJob1(a) {
        return cronTimeJob1;
    }

    @Value("${schedule.cron.withJob2}")
    private String cronTimeJob2;

    public String getCronTimeJob1(a) {
        return cronTimeJob2;
    }

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try{
            //job1 was deleted and then added
            log.info("job1: delete scheduleWithJob1");
            quartzService.deleteJob("scheduleWithJob1"."scheduleWithJob1_Group1");

            log.info("job1: add scheduleWithJob1");
            quartzService.addJob(ScheduleWithJob1.class, "scheduleWithJob1"."scheduleWithJob1_Group1", cronTimeJob1, null);

            // The hourly job was deleted and then added
            log.info("job2: delete scheduleWithJob2");
            quartzService.deleteJob("scheduleWithJob2"."scheduleWithJob2_Group2");

            log.info("job2: add scheduleWithJob2");
            quartzService.addJob(ScheduleWithJob2.class, "scheduleWithJob2"."scheduleWithJob2_Group2", cronTimeJob2, null);
        } catch (Exception e) {
            log.error("quartz service scheduler job failed!"); e.printStackTrace(); }}}Copy the code

Specific Job Task class

ScheduleWithJob1 class

package com.andya.selfcode.quartz;

import com.andya.selfcode.service.ScheduleJobService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.time.LocalDateTime;

/ * * *@author Andya
 * @create2021/04/01 * /
@Slf4j
public class ScheduleWithJob1 extends QuartzJobBean {

    @Autowired
    ScheduleJobService scheduleJobService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException{
        System.out.println("start schedule job1: " + LocalDateTime.now());
        try {
            scheduleJobService.scheduleWithJob1();
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

ScheduleWithJob2 class

package com.andya.selfcode.quartz;

import com.andya.selfcode.service.ScheduleJobService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.time.LocalDateTime;

/ * * *@author Andya
 * @create2021/04/01 * /
public class ScheduleWithJob2 extends QuartzJobBean {

    @Autowired
    ScheduleJobService scheduleJobService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {
            System.out.println("start schedule with job2: " + LocalDateTime.now());
            scheduleJobService.scheduleJob2();
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

ScheduleJobService interface class

package com.andya.selfcode.service;

/ * * *@author Andya
 * @create2021/04/01 * /
public interface ScheduleJobService {

    /** * job1 scheduled task *@throws Exception
     */
    void scheduleJob1(a) throws Exception;

    /** * Job2 scheduled task *@throws Exception
     */
    void scheduleJob2(a) throws Exception;
}

Copy the code

HTTP interface

Write a Controller layer that calls the QuartzService interface class directly.

package com.andya.selfcode.quartz.controller;

import com.andya.selfcode.quartz.bean.UpdateJobBean;
import com.andya.selfcode.quartz.bean.JobXXXBean;
import com.andya.selfcode.quartz.exception.BadRequestException;
import com.andya.selfcode.quartz.service.QuartzService;
import com.andya.selfcode.quartz.service.jobs.Job1;
import io.swagger.annotations.*;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/ * * *@author Andya
 * @create2021/04/01 * /
@RestController
@api (value = "quartz ")
@RequestMapping(value = "/quartz")
public class YarnFlexibleCapacityExpansionController {

    @Autowired
    QuartzService quartzService;

    @apiOperation (value = "add job with Quartz ")
    @RequestMapping(value = "/addJob/{jobUUID}", method = RequestMethod.POST)
    public void addQuartzJob(
            @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
            @ApiParam(name = "JobXXXBean") @RequestBody JobXXXBean jobXXXBean) {

        if(jobXXXBean.getOpenBean() ! =null) {
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("key01", jobXXXBean.getKey01());
            jobDataMap.put("key02", jobXXXBean.getKey02());
            jobDataMap.put("key03", jobXXXBean.getKey03());
            jobDataMap.put("jobTimeCron", jobXXXBean.getJobTimeCron());
            jobDataMap.put("key04", jobXXXBean.getKey04());
            quartzService.addJob(Job1.class,
                    jobUUID,
                    jobUUID,
                    jobXXXBean.getJobTimeCron(),
                    jobDataMap);
        } else {
            throw new BadRequestException("Parameter error"); }}@apiOperation (value = "query all jobs using Quartz ")
    @RequestMapping(value = "/queryAllJob", method = RequestMethod.GET)
    public List<Map<String, Object>> queryAllQuartzJob() {

        List<Map<String, Object>> list = quartzService.queryAllJob();
        return list;
    }


    @apiOperation (value = "query all running jobs using Quartz ")
    @RequestMapping(value = "/queryRunJob", method = RequestMethod.GET)
    public List<Map<String, Object>> queryRunQuartzJob() {

        List<Map<String, Object>> list = quartzService.queryRunJob();
        return list;
    }

    @apiOperation (value = "delete job using quartz ")
    @RequestMapping(value = "/deleteJob/{jobUUID}", method = RequestMethod.DELETE)
    public void deleteJob(
            @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID) {

        quartzService.deleteJob(jobUUID, jobUUID);
    }


    @apiOperation (value = "Change the cron time of the job using Quartz ")
    @RequestMapping(value = "/updateJob/{jobUUID}", method = RequestMethod.PUT)
    public void deleteJob(
            @ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
            @ApiParam(name = "jobCronTime") @RequestBody UpdateJobBean updateJobBean) { quartzService.updateJob(jobUUID, jobUUID, updateJobBean.getJobCronTime()); }}/ * * *@author Andya
 * @create2021/04/01 * /
@apiModel (value = "Update job cron time ")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UpdateJobBean {
    @apiModelProperty (value = "jobTime cron expression ", example = "0 0 1 * *? )
    String jobCronTime;

    public String getJobCronTime(a) {
        return jobCronTime;
    }

    public void setJobCronTime(String jobCronTime) {
        this.jobCronTime = jobCronTime; }}Copy the code

Quartz data table script

The SQL script for initializing the table is as follows.

-- 1.1. qrtz_blob_triggers: Triggers stored as a Blob.
-- 1.2. qrtz_calendars: A calendar can be configured to specify a time range.
-- 1.3. qrtz_cron_triggers: Place a CRON trigger.
-- 1.4. qrtz_fired_triggers: Save triggered triggers.
-- 1.5. Qrtz_job_details: Stores a jobDetail.
-- 1.6. Qrtz_job_listeners: Job listeners
-- 1.7. qrTZ_LOCKS: Stores pessimistic lock information for the program if pessimistic locks are used.
-- 1.8. qrTZ_PAused_trigger_graps: Holds paused triggers.
-- 1.9. qrTZ_scheduler_state: indicates the scheduler status.
-- 1.10. qrTZ_simple_Triggers: Information for simple triggers.
-- 1.11.qrtz_trigger_listeners
-- 1.12.qrTZ_Triggers: Basic information for triggers.

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(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) 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(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) 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(190) NULL,
JOB_GROUP VARCHAR(190) 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(190) 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;
Copy the code

refer by

www.quartz-scheduler.org/