Spring4+Springmvc+quartz realizes multi-threaded dynamic timing scheduling

The scheduler timing scheduling system is required by most industry projects. The traditional spring-job mode is out of my personal feeling, because there are many problems, especially the addition, modification, deletion of timing scheduling, etc., it is necessary to modify the xml, xml configuration Taking effect is nothing more than a hot deployment grayscale release scheme or directly stopping and restarting the server, which cannot be automatically started and repaired.

Reminder: The application can be deployed in a cluster. When configuring the timing scheduling, you can use the cluster mode or the unilateral configuration application mode. Today, I will explain the use of spring4+scheduler to achieve timing scheduling. Let’s cut down on the gossip and record the steps directly:

 

1. Introduce the quartz jar package into the pom.xml file of the project, as follows:

 <!-- quartz定时调度 -->  
lt;dependency>  
<groupId>org.quartz-scheduler</groupId>  
<artifactId>quartz</artifactId>  
<version>1.8.5</version>  
lt;/dependency> 

2. Define the quartz configuration file spring-context-quartz.xml:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"  
    default-lazy-init="false">  
    <!-- 调度器 -->  
    <bean name="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">   
       <!-- 通过applicationContextSchedulerContextKey属性配置spring上下文 -->      
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />  
    </bean>    
    <!--加载数据库任务-->  
    <bean id="jobService" class="com.ml.honghu.job.service.JobService" init-method="loadJob" />  
</beans> 

3. Introduce the spring-context-quartz.xml configuration file into the project's web.xml file

classpath*:spring-context-quartz.xml  

4. Define the job entity object

public class Job{  
      
    private static final long serialVersionUID = 1L;  
      
    /** 
     * 任务执行周期cron表达式 
     */  
    public static int EXECYCLE_CRON = 2;  
    /** 
     * 任务执行周期自定义 
     */  
    public static int EXECYCLE_DEFINE = 1;  
    /** 
     * 执行周期-分钟 
     */  
    public static int EXECYCLE_MINUTE = 1;  
    /** 
     * 执行周期-小时 
     */  
    public static int EXECYCLE_HOUR = 2;  
    /** 
     * 执行周期-日 
     */  
    public static int EXECYCLE_DAY = 3;  
    /** 
     * 执行周期-月 
     */  
    public static int EXECYCLE_WEEK = 4;  
    /** 
     * 执行周期-月 
     */  
    public static int EXECYCLE_MONTH = 5;  
      
  
    private String jobType;     // 任务类型(1首页静态化、2栏目页静态化、3内容页静态化、4采集、5分发)  
    private String jobName;     // 任务名称  
    private String jobClass;        // 任务类  
    private String execycle;        // 执行周期分类(1非表达式 2 cron表达式)  
    private String dayOfMonth;      // 每月的哪天  
    private String dayOfWeek;       // 周几  
    private String hour;        // 小时  
    private String minute;      // 分钟  
    private String intervalHour;        // 间隔小时  
    private String intervalMinute;      // 间隔分钟  
    private String jobIntervalUnit;     // 1分钟、2小时、3日、4周、5月  
    private String cronExpression;      // 规则表达式  
    private String isEnable;        // 是否启用  
      
    public Job() {  
        super();  
    }  
  
    public Job(String id){  
        super(id);  
    }  
  
    @Length(min=1, max=1, message="任务类型(1首页静态化、2栏目页静态化、3内容页静态化、4采集、5分发)长度必须介于 1 和 1 之间")  
    public String getJobType() {  
        return jobType;  
    }  
  
    public void setJobType(String jobType) {  
        this.jobType = jobType;  
    }  
      
    @Length(min=1, max=255, message="任务名称长度必须介于 1 和 255 之间")  
    public String getJobName() {  
        return jobName;  
    }  
  
    public void setJobName(String jobName) {  
        this.jobName = jobName;  
    }  
      
    @Length(min=1, max=255, message="任务类长度必须介于 1 和 255 之间")  
    public String getJobClass() {  
        return jobClass;  
    }  
  
    public void setJobClass(String jobClass) {  
        this.jobClass = jobClass;  
    }  
      
    @Length(min=1, max=1, message="执行周期分类(1非表达式 2 cron表达式)长度必须介于 1 和 1 之间")  
    public String getExecycle() {  
        return execycle;  
    }  
  
    public void setExecycle(String execycle) {  
        this.execycle = execycle;  
    }  
      
    @Length(min=0, max=11, message="每月的哪天长度必须介于 0 和 11 之间")  
    public String getDayOfMonth() {  
        return dayOfMonth;  
    }  
  
    public void setDayOfMonth(String dayOfMonth) {  
        this.dayOfMonth = dayOfMonth;  
    }  
      
    @Length(min=0, max=1, message="周几长度必须介于 0 和 1 之间")  
    public String getDayOfWeek() {  
        return dayOfWeek;  
    }  
  
    public void setDayOfWeek(String dayOfWeek) {  
        this.dayOfWeek = dayOfWeek;  
    }  
      
    @Length(min=0, max=11, message="小时长度必须介于 0 和 11 之间")  
    public String getHour() {  
        return hour;  
    }  
  
    public void setHour(String hour) {  
        this.hour = hour;  
    }  
      
    @Length(min=0, max=11, message="分钟长度必须介于 0 和 11 之间")  
    public String getMinute() {  
        return minute;  
    }  
  
    public void setMinute(String minute) {  
        this.minute = minute;  
    }  
      
    @Length(min=0, max=11, message="间隔小时长度必须介于 0 和 11 之间")  
    public String getIntervalHour() {  
        return intervalHour;  
    }  
  
    public void setIntervalHour(String intervalHour) {  
        this.intervalHour = intervalHour;  
    }  
      
    @Length(min=0, max=11, message="间隔分钟长度必须介于 0 和 11 之间")  
    public String getIntervalMinute() {  
        return intervalMinute;  
    }  
  
    public void setIntervalMinute(String intervalMinute) {  
        this.intervalMinute = intervalMinute;  
    }  
      
    @Length(min=0, max=1, message="1分钟、2小时、3日、4周、5月长度必须介于 0 和 1 之间")  
    public String getJobIntervalUnit() {  
        return jobIntervalUnit;  
    }  
  
    public void setJobIntervalUnit(String jobIntervalUnit) {  
        this.jobIntervalUnit = jobIntervalUnit;  
    }  
      
    @Length(min=0, max=255, message="规则表达式长度必须介于 0 和 255 之间")  
    public String getCronExpression() {  
        return cronExpression;  
    }  
  
    public void setCronExpression(String cronExpression) {  
        this.cronExpression = cronExpression;  
    }  
      
    @Length(min=1, max=1, message="是否启用长度必须介于 1 和 1 之间")  
    public String getIsEnable() {  
        return isEnable;  
    }  
  
    public void setIsEnable(String isEnable) {  
        this.isEnable = isEnable;  
    }  
      
}  

5. Write quartz's jobServvice class:

package com.ml.honghu.job.service;  
  
import java.text.ParseException;  
import java.util.List;  
import java.util.UUID;  
  
import org.quartz.CronTrigger;  
import org.quartz.JobDetail;  
import org.quartz.Scheduler;  
import org.quartz.SchedulerException;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Service;  
import org.springframework.transaction.annotation.Transactional;  
  
import com.ml.honghu.StringUtils;  
import com.ml.honghu.common.persistence.Page;  
import com.ml.honghu.common.service.CrudService;  
import com.ml.honghu.job.dao.JobDao;  
import com.ml.honghu.job.entity.Job;  
  
/** 
 * 定时调度任务Service 
 *  
 * @author honghu 
 */  
@Service  
@Transactional(readOnly = true)  
public class JobService extends CrudService<JobDao, Job> {  
      
    @Autowired  
    private JobDao jobDao;  
      
    private Logger logger = LoggerFactory.getLogger(getClass());  
  
    public Job get(String id) {  
        return super.get(id);  
    }  
  
    public List<Job> findList(Job job) {  
        return super.findList(job);  
    }  
  
    public Page<Job> findPage(Page<Job> page, Job job) {  
        return super.findPage(page, job);  
    }  
  
    @Transactional(readOnly = false)  
    public void save(Job job) {  
        super.save(job);  
        // 启用则启动任务  
        if (StringUtils.equals("1", job.getIsEnable())) {  
            startTask(job, job.getId());  
        }  
    }  
      
    @Transactional(readOnly = false)  
    public void update(Job job) {  
        //结束定时调度  
        endTask(job.getId());  
          
        job.preUpdate();  
        jobDao.update(job);  
          
        // 启用则启动任务  
        if (StringUtils.equals("1", job.getIsEnable())) {  
            startTask(job, job.getId());  
        }  
    }  
  
    @Transactional(readOnly = false)  
    public void delete(Job job) {  
        //结束任务  
        endTask(job.getId());  
          
        super.delete(job);  
    }  
  
    /** 
     * 系统初始加载任务 
     */  
    public void loadJob() throws Exception {  
        List<Job> jobList = this.findList(new Job());  
        if (null != jobList && jobList.size() > 0) {  
            for (int i = 0; i < jobList.size(); i++) {  
                Job job = jobList.get(i);  
                // 任务开启状态 执行任务调度  
                if (StringUtils.equals("1", job.getIsEnable())) {  
                    try {  
                        JobDetail jobDetail = new JobDetail();  
                        // 设置任务名称  
                        if (StringUtils.isNotBlank(job.getId())) {  
                            jobDetail.setName(job.getId());  
                        } else {  
                            UUID uuid = UUID.randomUUID();  
                            jobDetail.setName(uuid.toString());  
                            job.setId(uuid.toString());  
                        }  
                        jobDetail.setGroup(Scheduler.DEFAULT_GROUP);  
                        // 设置任务执行类  
                        jobDetail.setJobClass(getClassByTask(job.getJobClass()));  
                        // 添加任务参数  
                        CronTrigger cronTrigger = new CronTrigger("cron_" + i, Scheduler.DEFAULT_GROUP,  
                                jobDetail.getName(), Scheduler.DEFAULT_GROUP);  
  
                        cronTrigger.setCronExpression(getCronExpressionFromDB(job.getId()));  
                        // 调度任务  
                        scheduler.scheduleJob(jobDetail, cronTrigger);  
                    } catch (SchedulerException e) {  
                        logger.error("JobService SchedulerException", e);  
                    } catch (ClassNotFoundException e) {  
                        logger.error("JobService ClassNotFoundException", e);  
                    } catch (Exception e) {  
                        logger.error("JobService Exception", e);  
                    }  
                }  
            }  
        }  
    }  
  
    /** 
     *  
     * @param taskClassName 
     *            任务执行类名 
     * @return 
     * @throws ClassNotFoundException 
     */  
    @SuppressWarnings("rawtypes")  
    private Class getClassByTask(String taskClassName) throws ClassNotFoundException {  
        return Class.forName(taskClassName);  
    }  
  
    public String getCronExpressionFromDB(String id) throws Exception {  
        // 设置任务规则  
        Job job = this.get(id);  
        if (null != job) {  
            if (Job.EXECYCLE_CRON == Integer.parseInt(job.getExecycle())) {  
                return job.getCronExpression();  
            } else {  
                Integer execycle = Integer.parseInt(job.getJobIntervalUnit());  
                String excep = "";  
                if (execycle.equals(Job.EXECYCLE_MONTH)) {  
                    excep = "0  " + job.getMinute() + " " + job.getHour() + " " + job.getDayOfMonth() + " * ?";  
                } else if (execycle.equals(Job.EXECYCLE_WEEK)) {  
                    excep = "0  " + job.getMinute() + " " + job.getHour() + " " + " ? " + " * " + job.getDayOfWeek();  
                } else if (execycle.equals(Job.EXECYCLE_DAY)) {  
                    excep = "0  " + job.getMinute() + " " + job.getHour() + " " + " * * ?";  
                } else if (execycle.equals(Job.EXECYCLE_HOUR)) {  
                    excep = "0 0 */" + job.getIntervalHour() + " * * ?";  
                } else if (execycle.equals(Job.EXECYCLE_MINUTE)) {  
                    excep = "0  */" + job.getIntervalMinute() + " * * * ?";  
                }  
                return excep;  
            }  
        }  
        return "";  
    }  
  
    private void startTask(Job job, String id) {  
        try {  
            String cronExpress = getCronExpressionFromDB(id);  
            if (StringUtils.isNotEmpty(cronExpress) && cronExpress.indexOf("null") == -1) {  
                JobDetail jobDetail = new JobDetail();  
                jobDetail.setName(id);  
                jobDetail.setGroup(Scheduler.DEFAULT_GROUP);  
                jobDetail.setJobClass(getClassByTask(job.getJobClass()));  
                CronTrigger cronTrigger = new CronTrigger("cron_" + id, Scheduler.DEFAULT_GROUP, jobDetail.getName(),  
                        Scheduler.DEFAULT_GROUP);  
                cronTrigger.setCronExpression(cronExpress);  
                scheduler.scheduleJob(jobDetail, cronTrigger);  
            }  
        } catch (ParseException e) {  
            logger.error("JobService ParseException", e);  
        } catch (Exception e) {  
            logger.error("JobService Exception", e);  
        }  
    }  
      
    private void endTask(String id) {  
        try {  
            scheduler.deleteJob(id, Scheduler.DEFAULT_GROUP);  
        } catch (SchedulerException e) {  
            logger.error("JobService endTask", e);  
        }  
    }  
  
    @Autowired  
    private Scheduler scheduler;  
  
}  

6. I will not write the Controller, dao, and dao.xml of related jobs here. In fact, it is the operation of adding, deleting, modifying and checking data.

7. Start the project to verify that quartz is successful:

Sources of information and source code

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325516667&siteId=291194637