当前位置:网站首页>[quartz] read configuration from database to realize dynamic timing task

[quartz] read configuration from database to realize dynamic timing task

2022-06-26 04:55:00 Only empty city

Preface

         stay Java Medium timed tasks are common , Use @Scheduled Annotation can realize timing , However, in the production environment, you may encounter the self configuring timing time of the scheduled task on the page , Used alone in this case @Scheduled Annotations are hard to implement timed tasks , So we can store the scheduled tasks in the database and use quartz Realize dynamic timing task .


Configuration dependency

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
</dependency>

Realization way

1、 Scheduled task table entity

@Data
@TableName("SCHEDULE_JOB")
public class ScheduleJob {

    /**
     *  Serial number 
     */
    @TableId(value = "ID", type = IdType.ID_WORKER_STR)
    private String id;

    /**
     *  The name of the task 
     */
    @TableField("JOB_NAME")
    private String jobName;

    /**
     *  Task groups 
     */
    @TableField("JOB_GROUP")
    private String jobGroup;

    /**
     *  Task status   Whether to start the task ,2: invalid ;1: It works 
     */
    @TableField("JOB_STATUS")
    private Integer jobStatus;

    /**
     * cron expression , Recommended 6 Domain 
     */
    @TableField("CRON_EXPRESSION")
    private String cronExpression;

    /**
     *  describe 
     */
    @TableField("DESCRIPTION")
    private String description;

    /**
     *  Which class of methods is called when the task is executed   Package name + Class name , The full path 
     */
    @TableField("BEAN_CLASS")
    private String beanClass;

    /**
     *  Whether the task has status 
     */
    @TableField("IS_CONCURRENT")
    private Integer isConcurrent;

    /**
     * spring bean  The class name corresponding to the scheduled task , Initial lowercase 
     */
    @TableField("SPRING_ID")
    private String springId;

    /**
     *  The method name of the task call 
     */
    @TableField("method_name")
    private String methodName;

    @TableField("CREATE_TIME")
    private Date createTime;

    @TableField("UPDATE_TIME")
    private Date updateTime;
}

2、 Reflection call scheduleJob The method defined in

import com.saas.reptile.common.result.Result;
import com.saas.reptile.entity.po.ScheduleJob;
import com.saas.reptile.utils.LogUtils;
import com.saas.reptile.utils.SpringUtils;
import com.saas.reptile.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;

public class TaskUtils {

    @Autowired
    private ApplicationContext applicationContext;
    /**
     *  Call by reflection scheduleJob The method defined in 
     *
     * @param scheduleJob
     */
    public static void invokMethod(ScheduleJob scheduleJob) {

        try {// Add maximum exception catches 
            String springId = scheduleJob.getSpringId();
            Object object = null;
            Class clazz = null;

            // According to reflection 
            if (StringUtils.isNotBlank(springId)) {
                object = SpringUtils.getBean(springId);
            }

            if (object == null && StringUtils.isNotBlank(scheduleJob.getBeanClass())) {
                String jobStr = " Timing task name  = [" + scheduleJob.getJobName() + "]- stay spring  There is no such  springId,  adopt  class type  Getting ...";
                LogUtils.info(jobStr, scheduleJob.getBeanClass());
                try {
                    clazz = Class.forName(scheduleJob.getBeanClass());
                    object = SpringUtils.getBean(clazz);
                    if(object == null){
                        jobStr = " Timing task name  = [" + scheduleJob.getJobName() + "]- stay spring  Did not get  bean,  call  spring  Method is being built again ...";
                        LogUtils.info(jobStr, scheduleJob.getBeanClass());
                        object = SpringUtils.getBeanByType(clazz);
                    }
                    if (StringUtils.isNotBlank(springId)) {
                        SpringUtils.setBean(springId, object);
                        LogUtils.info("spring bean  The build is complete and added to the container  ", scheduleJob.getBeanClass());
                    }
                    LogUtils.info(" Timing task  spring bean  Building a successful ! ", scheduleJob.getBeanClass());
                } catch (Exception e) {
                    LogUtils.error(" Timing task  spring bean  The build failed !!! ", scheduleJob.getBeanClass(), e);
                    Result.fail(e);
                    return;
                }
            }

            clazz = object.getClass();
            Method method = null;
            try {
                method = clazz.getDeclaredMethod(scheduleJob.getMethodName());
            } catch (NoSuchMethodException e) {
                String jobStr = " Timing task name  = [" + scheduleJob.getJobName() + "] =  Not started successfully , Method name setting error !!!";
                LogUtils.error(jobStr, e);
            } catch (SecurityException e) {
                LogUtils.error("TaskUtils Something goes wrong ", e);
                Result.fail(e);
            }
            if (method != null) {
                try {
                    method.invoke(object);
                    LogUtils.info(" Timing task name  = [" + scheduleJob.getJobName() + "] =  Successful launch ");
                } catch (Exception e) {
                    Result.fail(e);
                    LogUtils.error(" Timing task name  = [" + scheduleJob.getJobName() + "] =  Failed to start !!!", e);
                    return;
                }
            } else {
                String jobStr = " Timing task name  = [" + scheduleJob.getJobName() + "] =  Failed to start !!!";
                LogUtils.error(jobStr, clazz.getName(), "not find method ");
            }

        } catch (Exception e) {// Add maximum exception catches 
            Result.fail(e);
            LogUtils.error(" Timing task name  = [" + scheduleJob.getJobName() + "] =  Failed to start !!!", e);
        }

    }
}

3、 Create... In normal state job Execution plant

import com.saas.reptile.entity.po.ScheduleJob;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class QuartzJobFactory implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
        TaskUtils.invokMethod(scheduleJob);
    }
}

4、 If a method cannot be executed at one time, the next operation will not be executed until the modified method is executed at the next rotation

import com.saas.reptile.entity.po.ScheduleJob;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution
public class QuartzJobFactoryDisallowConcurrentExecution implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
        TaskUtils.invokMethod(scheduleJob);
    }
}

5、 Create a scheduled task class that needs to be run

@Component
public class ClassAtmosphereTask {

    public void work(){
        // do something
    }

}

6、SpringBean Factory tools

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements BeanFactoryPostProcessor {

    // Spring Application context 
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    /**
     *  Get objects 
     *
     * @param name
     * @return Object  One registered under the given name bean Example 
     * @throws BeansException
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }

    /**
     *  Get objects 
     * @return Object  One registered under the given name bean Example 
     * @throws BeansException
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBeanByType(Class<T> clzee) throws BeansException {
        try {
            return beanFactory.createBean(clzee);
        } catch (NoSuchBeanDefinitionException e) {
            return null;
        }

    }

    /**
     *  Inject an object 
     * @return Object  One registered under the given name bean Example 
     * @throws BeansException
     */
    @SuppressWarnings("unchecked")
    public static void setBean(String springId, Object obj) throws BeansException {
        beanFactory.registerSingleton(springId, obj);
    }

    /**
     *  The acquisition type is requiredType The object of 
     * @return
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        try {
            @SuppressWarnings("unchecked")
            T result = (T) beanFactory.getBean(clz);
            return result;
        } catch (NoSuchBeanDefinitionException e) {
            return null;
        }
    }

    /**
     *  If BeanFactory Contains a... That matches the given name bean Definition , Then return to true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    /**
     *  Judge what is registered with a given name bean The definition is a singleton Or a prototype.
     *  If the given name corresponds to bean Definition not found , An exception will be thrown (NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws NoSuchBeanDefinitionException
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class  Type of registered object 
     * @throws NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getType(name);
    }

    /**
     *  If given bean Name in bean There are aliases in the definition , Then return these aliases 
     *
     * @param name
     * @return
     * @throws NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getAliases(name);
    }
}

7、 Other tools used

  • String utility class
public class StringUtils {
    public final static String REG_DIGIT = "[0-9]*";
    public final static String REG_CHAR = "[a-zA-Z]*";
    public final static String EMPTY = "";

    /**
     *  Determine whether it is null 
     */
    public static boolean isEmpty(Object... obj) {
        if(obj == null)
            return true;
        for(Object object : obj) {
            if (object == null)
                return true;
            if (object.toString().trim().length() == 0)
                return true;
        }

        return false;
    }

    public static boolean isBlankEmpty(Object obj) {
        if (obj == null || "".equals(obj) || "".equals(obj.toString().trim()) || "null".equalsIgnoreCase(obj.toString()))
            return true;

        return false;
    }

    /**
     *  Is it empty , Or an empty string , Or for "null"
     * @author guoyu
     */
    public static boolean isBlankEmpty(Object... objs) {
        if (objs == null || objs.length == 0)
            return true;
        for (Object obj : objs) {
            if (isBlankEmpty(obj)) {
                return true;
            }
        }

        return false;
    }

    public static boolean isNotBlank(String pattern) {
        return !isBlankEmpty(pattern);
    }

    public static boolean isBlank(String pattern) {
        return isBlankEmpty(pattern);
    }

    public static String formatCountNames(String nameList) {
        String[] names = nameList.split(",");

        Map<String, Integer> nameCount = new HashMap<String, Integer>();
        for(String name : names) {
            if(StringUtils.isEmpty(name)) continue;
            if(nameCount.containsKey(name)) {
                Integer count = nameCount.get(name) + 1;
                nameCount.put(name, count);
            } else {
                nameCount.put(name, 1);
            }
        }

        StringBuilder newNames = new StringBuilder();
        for(String key : nameCount.keySet()) {
            if(StringUtils.isEmpty(key)) continue;
            Integer count = nameCount.get(key);
            String splitChar = newNames.length() > 0 ? "," : "";
            newNames.append(splitChar).append(key).append("x").append(count);
        }

        return newNames.toString();
    }


    public static boolean isDigit(String str){
        return isNumeric(str);
    }

    public static boolean isChar(String str){
        return str.matches(REG_CHAR);
    }

    public static Boolean isNotEmpty(Object... obj) {
        Boolean r = StringUtils.isEmpty(obj);
        return !r;
    }

    public static boolean isNumeric(String str) {
        if(isBlankEmpty(str)) return false;
        for (int i = str.length(); --i >= 0;) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * string  Medium  str  In the countdown  num  Position in 
     * @author guoyu
     */
    public static int stringLastlndex(String string, String str, int num) {
        int indexOf = string.lastIndexOf(str);
        if(num > 1){
            return stringLastlndex(string.substring(0, indexOf), str, num - 1);
        } else {
            return indexOf;
        }
    }


    public static String getValue(Object val) {
        return val == null ? "" : val.toString().replace("\n", "");
    }

    public static String getFileName(boolean type, Date startDate, String tableName){
        String dateString = dateFormat(startDate,"yyyyMMdd");
        StringBuffer stringBuffer = new StringBuffer(dateString);
        stringBuffer.append("_");
        stringBuffer.append(tableName);
        stringBuffer.append("_");
        if (type) {
            stringBuffer.append("insert&");
        } else {
            stringBuffer.append("update&");
        }
        return stringBuffer.toString();
    }

    public static String getRefundNumber(Integer payRefundNum) {
        if (payRefundNum == null) payRefundNum = 0;
        payRefundNum = payRefundNum + 1;
        String string = String.valueOf(payRefundNum);
        if (string.length() == 1) {
            return "0"+string;
        }
        return string;

    }

    private static String dateFormat(Date date, String datePattern) {
        if(date == null) return "";
        if(datePattern == null) datePattern = "yyyy-MM-dd";
        SimpleDateFormat df = new SimpleDateFormat(datePattern, Locale.UK);
        return df.format(date);
    }
}
  • Log tool class
import org.apache.commons.logging.LogFactory;


public class LogUtils {
    private static final org.apache.commons.logging.Log logger;
    private static final Object lock = new Object();

    static {
        synchronized (lock) {
            logger = LogFactory.getLog(LogUtils.class);
        }
    }

    public static void info(Object... msgs) {
        StringBuilder stringBuilder = new StringBuilder();
        Throwable e = null;
        for (Object msg : msgs) {
            if (msg != null) {
                if (msg instanceof Throwable) {
                    e = (Throwable) msg;
                } else {
                    stringBuilder.append(msg).append(" ");
                }
            }
        }
        logger.info(stringBuilder, e);
    }

    public static void error(Object... msgs) {
        StringBuilder stringBuilder = new StringBuilder();
        Throwable e = null;
        for (Object msg : msgs) {
            if (msg != null) {
                if (msg instanceof Throwable) {
                    e = (Throwable) msg;
                } else {
                    stringBuilder.append(msg).append(" ");
                }
            }
        }
        logger.error(stringBuilder, e);
    }

    public static void warn(Object... msgs) {
        StringBuilder stringBuilder = new StringBuilder();
        Throwable e = null;
        for (Object msg : msgs) {
            if (msg != null) {
                if (msg instanceof Throwable) {
                    e = (Throwable) msg;
                } else {
                    stringBuilder.append(msg).append(" ");
                }
            }
        }
        logger.warn(stringBuilder, e);
    }

    public static void debug(Object... msgs) {
        StringBuilder stringBuilder = new StringBuilder();
        Throwable e = null;
        for (Object msg : msgs) {
            if (msg != null) {
                if (msg instanceof Throwable) {
                    e = (Throwable) msg;
                } else {
                    stringBuilder.append(msg).append(" ");
                }
            }
        }
        logger.debug(stringBuilder, e);
    }
}
  • Data analysis constant class
public final class Constant {

    private Constant() {
    }

    //  Scheduled task running status : function 
    public static final Integer STATUS_RUNNING = 1;

    //  Scheduled task running status : stop it 
    public static final Integer STATUS_NOT_RUNNING = 2;

    //  Whether the scheduled task has status : Yes ( The default is 1, Abandoning )
    public static final Integer CONCURRENT_IS = 1;

    //  Whether the scheduled task has status : nothing ( The default is 1, Abandoning )
    public static final Integer CONCURRENT_NOT = 0;
}
  • Interface return parameter class
@Data
public class Result<T> {

    private Integer code;

    private T data;

    private String msg;

    public Result() {
        super();
    }

    public Result(T data) {
        this.data = data;
    }

    public static Result success()
    {
        return success("");
    }

    public static <T> Result success(T data) {
        Result<T> result = new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getName());
        result.setData(data);
        return result;
    }

    public static <T> Result<T> fail(ResultEnum resultEnum) {
        return createResult(null, resultEnum.getCode(), resultEnum.getName());
    }

    public static <T> Result<T> fail(Integer code, String message) {
        return createResult(null, code, message);
    }

    public static <T> Result<T> fail(Throwable e) {
        // Print the exception stack information to the console 
        e.printStackTrace();
        return createResult(null, 500, " Server error ");
    }

    private static <T> Result<T> createResult(T data, Integer code, String message) {
        Result<T> r = new Result<>();
        r.setCode(code);
        r.setData(data);
        r.setMsg(message);
        return r;
    }

    public Result(Integer code, String msg)
    {
        this.code = code;
        this.msg = msg;
    }
}

among ResultEnum The categories are as follows :

public enum ResultEnum {

    SUCCESS(200," The request is successful "),
    UN_KNOWN_ERROR(-1, " Unknown error "),

    PARAM_NULL_ERROR(10001," The parameter is empty. "),

    PERMISSION_ACCESS_DENIED(50001, "permission access denied");


    private int code;
    private String name;

    private ResultEnum(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return this.code;
    }

    public String getName() {
        return this.name;
    }

    public static ResultEnum getNameByCode(int code) {
        for (ResultEnum resultEnum : ResultEnum.values()) {
            if (code == resultEnum.getCode()) {
                return resultEnum;
            }
        }
        return null;
    }
}

8、sql sentence

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for schedule_job
-- ----------------------------
DROP TABLE IF EXISTS `schedule_job`;
CREATE TABLE `schedule_job`  (
  `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT ' Primary key ',
  `job_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' The name of the task ',
  `job_group` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' Task groups ',
  `job_status` int(0) DEFAULT NULL COMMENT ' Task status   Whether to start the task ;1: It works ;2: invalid ',
  `cron_expression` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'cron expression , Recommended 6 Domain ',
  `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' Timed task description ',
  `bean_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' Which class of methods is called when the task is executed   Package name + Class name , The full path ',
  `is_concurrent` int(0) DEFAULT 1 COMMENT ' Whether the task has status ;0: No, ;1: Yes ',
  `spring_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' Registered Bean, So keep consistent with the class name , Initial lowercase ',
  `method_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT ' The method name of the task call ',
  `create_time` datetime(0) DEFAULT NULL COMMENT ' Creation time ',
  `update_time` datetime(0) DEFAULT NULL COMMENT ' Update time ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of schedule_job
-- ----------------------------
INSERT INTO `schedule_job` VALUES ('1', 'ClassAtmosphereTask', 'ClassAtmosphereTask', 1, '0 30 23 * * ?', ' Class atmosphere value fixed task ', 'com.saas.reptile.task.ClassAtmosphereTask', 1, 'classAtmosphereTask', 'work', '2022-06-25 21:38:42', '2022-06-25 21:38:45');

SET FOREIGN_KEY_CHECKS = 1;

The notes are very detailed , among :

job_name and job_group Keep consistent ;

is_concurrent The default is 1;

The class of task execution should be full path and so on .

9、 Method realization

Written in service In the implementation class of

package com.saas.reptile.service.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.saas.reptile.common.quartz.QuartzJobFactory;
import com.saas.reptile.common.quartz.QuartzJobFactoryDisallowConcurrentExecution;
import com.saas.reptile.entity.po.ScheduleJob;
import com.saas.reptile.mapper.ScheduleJobMapper;
import com.saas.reptile.service.ScheduleJobService;
import com.saas.reptile.utils.Constant;
import com.saas.reptile.utils.LogUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


@Service
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob>
        implements ScheduleJobService {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    /**
     *  Add scheduled tasks to the database 
     * @param scheduleJob
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addTask(ScheduleJob scheduleJob) {
        this.baseMapper.insert(scheduleJob);
    }

    /**
     *  Change the status of scheduled tasks 
     * @param id
     * @param status
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void changeJobStatus(String id, Integer status) throws SchedulerException {
//        EntityWrapper<ScheduleJob> wrapper = new EntityWrapper<>();
//        wrapper.eq("id",id);
//        String setSql = "job_status = " + status;
//        this.baseMapper.updateForSet(setSql, wrapper);
        ScheduleJob job = selectById(id);
        if (status == 1){
            //  start-up 
            job.setJobStatus(status);
            addJob(job);
        } else if (status == 2) {
            //  stop it 
            deleteJob(job);
            job.setJobStatus(status);
        }
        //  Update scheduled tasks 
        updateById(job);
    }

    /**
     *  Update scheduled tasks cron Expression and running state 
     * @param jobId      Scheduled task PK ID
     * @param cron       expression 
     * @param status     Timing status 
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateCronStatus(String jobId, String cron, Integer status) throws SchedulerException {
        ScheduleJob job = selectById(jobId);
        if (status == 1){
            //  start-up 
            job.setJobStatus(status);
            job.setCronExpression(cron);
            addJob(job);
        } else if (status == 2) {
            //  stop it 
            deleteJob(job);
            job.setJobStatus(status);
            job.setCronExpression(cron);
        }
        //  Update scheduled tasks 
        updateById(job);
    }

    /**
     *  Add tasks 
     *
     * @param job
     * @throws SchedulerException
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addJob(ScheduleJob job) throws SchedulerException {
        //  The running status of the scheduled task is 1 Then go to the next step 
        if (job == null || !Constant.STATUS_RUNNING.equals(job.getJobStatus())) {
            return;
        }
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        LogUtils.info(scheduler + ".......................................................................................add");
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        //  non-existent , Create a 
        if (null == trigger) {
            Class clazz = Constant.CONCURRENT_IS.equals(job.getIsConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class;

            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).build();

            jobDetail.getJobDataMap().put("scheduleJob", job);

            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

            trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } else {
            // Trigger Already exists , Then update the corresponding timing settings 
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

            //  Press new cronExpression Expression rebuild trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            //  Press new trigger To reset job perform 
            scheduler.rescheduleJob(triggerKey, trigger);
        }
    }

    @PostConstruct
    public void init() throws Exception {
        LogUtils.info(" Instantiation List<ScheduleJob>, Read from database ....",this);
        //  Get the task information data here 
        List<ScheduleJob> jobList = selectList(null);
        for (ScheduleJob job : jobList) {
            addJob(job);
        }
    }

    /**
     *  Get a list of all scheduled tasks 
     *
     * @return
     * @throws SchedulerException
     */
    public List<ScheduleJob> getAllJob() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        for (JobKey jobKey : jobKeys) {
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                ScheduleJob job = new ScheduleJob();
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setDescription(" trigger :" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setJobStatus(Integer.parseInt(triggerState.name()));
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }

    /**
     *  All the running job
     *
     * @return
     * @throws SchedulerException
     */
    public List<ScheduleJob> getRunningJob() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
        for (JobExecutionContext executingJob : executingJobs) {
            ScheduleJob job = new ScheduleJob();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            job.setJobName(jobKey.getName());
            job.setJobGroup(jobKey.getGroup());
            job.setDescription(" trigger :" + trigger.getKey());
            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            job.setJobStatus(Integer.parseInt(triggerState.name()));
            if (trigger instanceof CronTrigger) {
                CronTrigger cronTrigger = (CronTrigger) trigger;
                String cronExpression = cronTrigger.getCronExpression();
                job.setCronExpression(cronExpression);
            }
            jobList.add(job);
        }
        return jobList;
    }

    /**
     *  Suspend one job
     *
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    /**
     *  Restore one job
     *
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    /**
     *  Delete one job
     *
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void deleteJob(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.deleteJob(jobKey);

    }

    /**
     *  Execute now job
     *
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void runAJobNow(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    /**
     *  to update job Time expression 
     *
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void updateJobCron(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());

        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

        scheduler.rescheduleJob(triggerKey, trigger);
    }
}

1、 After the project is started, first run the init() Method , Query all scheduled tasks in the database table ;

2、 Then add to job Method 【addJob】, Set the state to 1 The scheduled task of is pushed to Scheduler Planned

3、 It also provides access to a list of all scheduled tasks 、 Query running job、 Suspend one job Other methods , But I haven't used it yet .

4、 This project is through mybatis-plus Perform database operations , When updating the running status , If the state is 1 Start up job, If the state is 2 Then stop job.

5、 The control layer method is omitted , According to the actual production environment .

Reference material :https://gitee.com/gangye/springboot_quartz_schedule

原网站

版权声明
本文为[Only empty city]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260448001092.html