最简单的SpringBoot 整合Quartz-教程-持久化到数据库

背景: 项目中很多时候会有一些定时任务,而这些定时任务在特殊时期还有可能改变运行周期,这时候框架quartz就很好的解决了这个问题


 项目结构图

Springboot直接支持该依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
 </dependency>

数据库中表SQL

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_job_quartz
-- ----------------------------
DROP TABLE IF EXISTS `sys_job_quartz`;
CREATE TABLE `sys_job_quartz`  (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务名',
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务描述',
  `cron_expression` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式',
  `expression_desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表达式描述',
  `bean_class` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名',
  `job_status` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '任务状态 0:停止 1:运行 2:暂停 -1:删除',
  `job_group` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'report' COMMENT '任务分组',
  `creator` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `modifier` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
  `modify_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

下面是具体的代码 

quartz配置类,config/quartz.properties配置文件可以在Resources中添加,可增加各种配置,这里暂且不使用

package com.milla.study.netbase.expert.quartz.config;

import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import java.io.IOException;
import java.util.Properties;

/**
 * @Package: com.milla.study.netbase.expert.quartz.config
 * @Description: <动态任务配置类>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:36
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:36
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Configuration
public class QuartzConfig {
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("quartz") Properties properties) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        try {
            schedulerFactoryBean.setOverwriteExistingJobs(true);
            schedulerFactoryBean.setQuartzProperties(properties);
            schedulerFactoryBean.setJobFactory(new SpringBeanJobFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return schedulerFactoryBean;
    }

    // 指定quartz.properties,可在配置文件中配置相关属性
    @Bean("quartz")
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
//            propertiesFactoryBean.setLocation(new ClassPathResource("/config/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    // 创建schedule
    @Bean(name = "scheduler")
    public Scheduler scheduler(SchedulerFactoryBean scheduler) {
        return scheduler.getScheduler();
    }
}

 任务实体类

package com.milla.study.netbase.expert.quartz.dto;

import lombok.Data;

import java.util.Date;

/**
 * @Package: com.milla.study.netbase.expert.quartz.dto
 * @Description: <任务实体>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:40
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:40
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Data
public class QuartzJobDTO {
    /**
     * 主键
     */
    private Integer id;
    /**
     * 任务名
     */
    private String jobName;
    /**
     * 任务描述
     */
    private String description;
    /**
     * cron表达式
     */
    private String cronExpression;
    /**
     * 表达式描述
     */
    private String expressionDesc;
    /**
     * 任务执行时调用哪个类的方法 包名+类名
     */
    private String beanClass;
    /**
     * 任务状态
     */
    private String jobStatus;
    /**
     * 任务分组
     */
    private String jobGroup;
    /**
     * 创建者
     */
    private String creator;
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新者
     */
    private String modifier;
    /**
     * 更新时间
     */
    private Date modifyTime;
}

任务操作类[包含启动任务,暂停任务,重启任务,修改任务等等] 

package com.milla.study.netbase.expert.quartz.util;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @Package: com.milla.study.netbase.expert.quartz.util
 * @Description: <计划任务管理>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:52
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:52
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Component
public class QuartzManager {

    @Autowired
    private Scheduler scheduler;

    /**
     * 增加一个任务
     *
     * @param job 任务
     * @throws SchedulerException     调度异常
     * @throws ClassNotFoundException 类找不到
     */
    public void addJob(QuartzJobDTO job) throws SchedulerException, ClassNotFoundException {
        //加载指定任务的实例class文件
        Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(job.getBeanClass()));
        // 任务名称和组构成任务key
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(job.getJobName(), job.getJobGroup()).build();
        // 定义调度触发规则
        // 使用cornTrigger规则
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())// 触发器key
                .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).startNow().build();
        // 把作业和触发器注册到任务调度中
        scheduler.scheduleJob(jobDetail, trigger);
        // 启动
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     * @throws SchedulerException
     */
    public List<QuartzJobDTO> listJob() throws SchedulerException {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<QuartzJobDTO> jobList = new ArrayList<>();
        for (JobKey jobKey : jobKeys) {
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                QuartzJobDTO job = new QuartzJobDTO();
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setDescription("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setJobStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }

    /**
     * 所有正在运行的job
     *
     * @return
     * @throws SchedulerException
     */
    public List<QuartzJobDTO> listRunningJob() throws SchedulerException {
        List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
        List<QuartzJobDTO> jobList = new ArrayList<QuartzJobDTO>(executingJobs.size());
        for (JobExecutionContext executingJob : executingJobs) {
            QuartzJobDTO job = new QuartzJobDTO();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            job.setJobName(jobKey.getName());
            job.setJobGroup(jobKey.getGroup());
            job.setDescription("触发器:" + trigger.getKey());
            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            job.setJobStatus(triggerState.name());
            if (trigger instanceof CronTrigger) {
                CronTrigger cronTrigger = (CronTrigger) trigger;
                String cronExpression = cronTrigger.getCronExpression();
                job.setCronExpression(cronExpression);
            }
            jobList.add(job);
        }
        return jobList;
    }

    /**
     * 暂停一个job
     *
     * @param job
     * @throws SchedulerException
     */
    public void pauseJob(QuartzJobDTO job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复一个job
     *
     * @param job
     * @throws SchedulerException
     */
    public void resumeJob(QuartzJobDTO job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除一个job
     *
     * @param job
     * @throws SchedulerException
     */
    public void deleteJob(QuartzJobDTO job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.deleteJob(jobKey);

    }

    /**
     * 立即执行job
     *
     * @param job
     * @throws SchedulerException
     */
    public void runJobNow(QuartzJobDTO job) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    /**
     * 更新job时间表达式
     *
     * @param job
     * @throws SchedulerException
     */
    public void updateJobCron(QuartzJobDTO job) throws SchedulerException {

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

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

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

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

        scheduler.rescheduleJob(triggerKey, trigger);
    }
}

Mapper文件

package com.milla.study.netbase.expert.quartz.mapper;


import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface QuartzJobDTOMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(QuartzJobDTO record);

    int insertSelective(QuartzJobDTO record);

    QuartzJobDTO selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(QuartzJobDTO record);

    int updateByPrimaryKey(QuartzJobDTO record);

    List<QuartzJobDTO> selectJob();

    List<QuartzJobDTO> selectJobByGroup(@Param("report") String report);

    QuartzJobDTO selectByJobName(QuartzJobDTO job);
}

 与之对应的xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.milla.study.netbase.expert.quartz.mapper.QuartzJobDTOMapper">
    <resultMap id="BaseResultMap" type="com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="job_name" property="jobName" jdbcType="VARCHAR"/>
        <result column="description" property="description" jdbcType="VARCHAR"/>
        <result column="cron_expression" property="cronExpression" jdbcType="VARCHAR"/>
        <result column="expression_desc" property="expressionDesc" jdbcType="VARCHAR"/>
        <result column="bean_class" property="beanClass" jdbcType="VARCHAR"/>
        <result column="job_status" property="jobStatus" jdbcType="VARCHAR"/>
        <result column="job_group" property="jobGroup" jdbcType="VARCHAR"/>
        <result column="creator" property="creator" jdbcType="VARCHAR"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="modifier" property="modifier" jdbcType="VARCHAR"/>
        <result column="modify_time" property="modifyTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
    id, job_name, description, cron_expression, expression_desc, bean_class, job_status, job_group, creator,
    create_time, modifier, modify_time
  </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List"/>
        from sys_job_quartz
        where id = #{id,jdbcType=INTEGER}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from sys_job_quartz
    where id = #{id,jdbcType=INTEGER}
  </delete>
    <insert id="insert" parameterType="com.aimsphm.nuclear.common.quartz.dto.QuartzJobDTO">
        <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into sys_job_quartz (job_name, description, cron_expression,expression_desc,
        bean_class, job_status, job_group,
        creator, create_time, modifier,
        modify_time)
        values (#{jobName,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
        #{cronExpression,jdbcType=VARCHAR},#{expressionDesc,jdbcType=VARCHAR}
        #{beanClass,jdbcType=VARCHAR}, #{jobStatus,jdbcType=VARCHAR}, #{jobGroup,jdbcType=VARCHAR},
        #{creator,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{modifier,jdbcType=VARCHAR},
        #{modifyTime,jdbcType=TIMESTAMP})
    </insert>
    <insert id="insertSelective" parameterType="com.aimsphm.nuclear.common.quartz.dto.QuartzJobDTO">
        <selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into sys_job_quartz
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="jobName != null">
                job_name,
            </if>
            <if test="description != null">
                description,
            </if>
            <if test="cronExpression != null">
                cron_expression,
            </if>
            <if test="expressionDesc!= null">
                expression_desc,
            </if>
            <if test="beanClass != null">
                bean_class,
            </if>
            <if test="jobStatus != null">
                job_status,
            </if>
            <if test="jobGroup != null">
                job_group,
            </if>
            <if test="creator != null">
                creator,
            </if>
            <if test="createTime != null">
                create_time,
            </if>
            <if test="modifier != null">
                modifier,
            </if>
            <if test="modifyTime != null">
                modify_time,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="jobName != null">
                #{jobName,jdbcType=VARCHAR},
            </if>
            <if test="description != null">
                #{description,jdbcType=VARCHAR},
            </if>
            <if test="cronExpression != null">
                #{cronExpression,jdbcType=VARCHAR},
            </if>
            <if test="expressionDesc != null">
                #{expressionDesc,jdbcType=VARCHAR},
            </if>
            <if test="beanClass != null">
                #{beanClass,jdbcType=VARCHAR},
            </if>
            <if test="jobStatus != null">
                #{jobStatus,jdbcType=VARCHAR},
            </if>
            <if test="jobGroup != null">
                #{jobGroup,jdbcType=VARCHAR},
            </if>
            <if test="creator != null">
                #{creator,jdbcType=VARCHAR},
            </if>
            <if test="createTime != null">
                #{createTime,jdbcType=TIMESTAMP},
            </if>
            <if test="modifier != null">
                #{modifier,jdbcType=VARCHAR},
            </if>
            <if test="modifyTime != null">
                #{modifyTime,jdbcType=TIMESTAMP},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="com.aimsphm.nuclear.common.quartz.dto.QuartzJobDTO">
        update sys_job_quartz
        <set>
            <if test="jobName != null">
                job_name = #{jobName,jdbcType=VARCHAR},
            </if>
            <if test="description != null">
                description = #{description,jdbcType=VARCHAR},
            </if>
            <if test="cronExpression != null">
                cron_expression = #{cronExpression,jdbcType=VARCHAR},
            </if>
            <if test="expressionDesc != null">
                expression_desc = #{expressionDesc,jdbcType=VARCHAR},
            </if>
            <if test="beanClass != null">
                bean_class = #{beanClass,jdbcType=VARCHAR},
            </if>
            <if test="jobStatus != null">
                job_status = #{jobStatus,jdbcType=VARCHAR},
            </if>
            <if test="jobGroup != null">
                job_group = #{jobGroup,jdbcType=VARCHAR},
            </if>
            <if test="creator != null">
                creator = #{creator,jdbcType=VARCHAR},
            </if>
            <if test="createTime != null">
                create_time = #{createTime,jdbcType=TIMESTAMP},
            </if>
            <if test="modifier != null">
                modifier = #{modifier,jdbcType=VARCHAR},
            </if>
            <if test="modifyTime != null">
                modify_time = #{modifyTime,jdbcType=TIMESTAMP},
            </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="com.aimsphm.nuclear.common.quartz.dto.QuartzJobDTO">
    update sys_job_quartz
    set job_name = #{jobName,jdbcType=VARCHAR},
      description = #{description,jdbcType=VARCHAR},
      cron_expression = #{cronExpression,jdbcType=VARCHAR},
      expression_desc = #{expressionDesc,jdbcType=VARCHAR},
      bean_class = #{beanClass,jdbcType=VARCHAR},
      job_status = #{jobStatus,jdbcType=VARCHAR},
      job_group = #{jobGroup,jdbcType=VARCHAR},
      creator = #{creator,jdbcType=VARCHAR},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      modifier = #{modifier,jdbcType=VARCHAR},
      modify_time = #{modifyTime,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=INTEGER}
  </update>
    <select id="selectJob" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_job_quartz
        where job_status =1
    </select>
    <select id="selectJobByGroup" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_job_quartz
        where job_status =1 and job_group='report'
    </select>
    <select id="selectByJobName" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_job_quartz
        where job_name=#{jobName} and job_group= #{jobGroup}
    </select>
</mapper>

 任务状态枚举类

package com.milla.study.netbase.expert.quartz.enums;

/**
 * @Package: com.milla.study.netbase.expert.quartz.enums
 * @Description: <>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:58
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:58
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public enum QuartzJobStateEnum {


    STOPPED("0", "停止"),

    RUNNING("1", "运行"),

    DELETED("-1", "删除");


    private String value;
    private String code;

    private QuartzJobStateEnum(String code, String value) {
        this.value = value;
        this.code = code;
    }

    public static QuartzJobStateEnum instance(String code) {
        for (QuartzJobStateEnum e : QuartzJobStateEnum.values()) {
            if (e.getCode().equals(code)) {
                return e;
            }
        }
        return null;
    }

    /**
     * 获取value
     */
    public String getValue() {
        return value;
    }

    /**
     * 获取code
     */
    public String getCode() {
        return code;
    }
}

任务操作枚举类 

package com.milla.study.netbase.expert.quartz.enums;

/**
 * @Package: com.milla.study.netbase.expert.quartz.enums
 * @Description: <对job进行的操作>
 * @Author: MILLA
 * @CreateDate: 2020/5/13 13:43
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/13 13:43
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public enum QuartzJobOperateEnum {
    stop, resume, update
}

 任务操作业务接口

package com.milla.study.netbase.expert.quartz.service;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobOperateEnum;
import org.quartz.SchedulerException;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service
 * @Description: <>
 * @Author: MILLA
 * @CreateDate: 2020/5/13 13:34
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/13 13:34
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public interface QuartzManagerService {
    void addJob(QuartzJobDTO job) throws ClassNotFoundException, SchedulerException;

    void modifyJob(Integer id, QuartzJobOperateEnum operateEnum, QuartzJobDTO job) throws SchedulerException;

    void removeJob(Integer id) throws SchedulerException;
}

 任务操作实现类

package com.milla.study.netbase.expert.quartz.service.impl;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobOperateEnum;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobStateEnum;
import com.milla.study.netbase.expert.quartz.mapper.QuartzJobDTOMapper;
import com.milla.study.netbase.expert.quartz.service.QuartzManagerService;
import com.milla.study.netbase.expert.quartz.util.QuartzManager;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service.impl
 * @Description: <任务管理业务类>
 * @Author: MILLA
 * @CreateDate: 2020/5/13 13:34
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/13 13:34
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Service
//在微服务中,该类按需启用使用下面的注解,该类能完成自动注入和不注入
@ConditionalOnProperty(prefix = "mybatis-plus", name = "quarzt-enable", havingValue = "1")
public class QuartzManagerServiceImpl implements QuartzManagerService {
    @Autowired
    private QuartzManager manager;

    @Autowired(required = false)
    private QuartzJobDTOMapper mapper;

    @Override
    @Transactional
    public void addJob(QuartzJobDTO job) throws ClassNotFoundException, SchedulerException {
        Assert.hasText(job.getJobName(), "任务名称不能为空");
        Assert.hasText(job.getCronExpression(), "任务执行周期不能为空");
        Assert.hasText(job.getJobGroup(), "任务分组不能为空");
        QuartzJobDTO find = mapper.selectByJobName(job);
        Assert.isNull(find, "要添加的任务已经存在");
        mapper.insertSelective(job);
        manager.addJob(job);
    }

    @Override
    public void modifyJob(Integer id, QuartzJobOperateEnum operateEnum, QuartzJobDTO job) throws SchedulerException {


        QuartzJobDTO find = mapper.selectByPrimaryKey(id);
        Assert.notNull(find, "要操作的任务不存在");
        if (StringUtils.hasText(job.getJobName())) {
            find.setJobName(job.getJobName());
        }
        if (StringUtils.hasText(job.getJobGroup())) {
            find.setJobGroup(job.getJobGroup());
        }
        if (StringUtils.hasText(job.getBeanClass())) {
            find.setBeanClass(job.getBeanClass());
        }
        if (StringUtils.hasText(job.getModifier())) {
            find.setModifier(job.getModifier());
        }
        switch (operateEnum) {
            //删除
            case stop:
                find.setJobStatus(QuartzJobStateEnum.STOPPED.getCode());
                manager.pauseJob(find);
                break;
            case resume:
                find.setJobStatus(QuartzJobStateEnum.RUNNING.getCode());
                manager.resumeJob(find);
                break;
            case update:
                if (StringUtils.isEmpty(job.getCronExpression())) {
                    throw new RuntimeException("任务表达式书写错误");
                }
                find.setCronExpression(job.getCronExpression());
                manager.updateJobCron(find);
                break;
            default:
                throw new RuntimeException("任务不支持该操作");
        }
        mapper.updateByPrimaryKeySelective(find);
    }

    @Override
    public void removeJob(Integer id) throws SchedulerException {
        QuartzJobDTO find = mapper.selectByPrimaryKey(id);
        Assert.notNull(find, "要操作的任务不存在");
        find.setJobStatus("-1");
        mapper.updateByPrimaryKeySelective(find);
        manager.deleteJob(find);
    }
}

 controller层控制类

package com.milla.study.netbase.expert.quartz.controller;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobOperateEnum;
import com.milla.study.netbase.expert.quartz.service.QuartzManagerService;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

/**
 * @Package: com.milla.study.netbase.expert.quartz.controller
 * @Description: <>
 * @Author: MILLA
 * @CreateDate: 2020/5/13 13:23
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/13 13:23
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@RestController
//@Api(tags = "任务管理")
@RequestMapping(value = "quartz", produces = MediaType.APPLICATION_JSON_VALUE)
public class QuartzJobController {

    @Autowired(required = false)
    private QuartzManagerService service;

    @PostMapping
    //@ApiOperation(value = "新增任务")
    public void addJob(@RequestBody QuartzJobDTO job) throws ClassNotFoundException, SchedulerException {
        checkService();
        service.addJob(job);
    }

    private void checkService() {
        if (service == null) {
            throw new RuntimeException("当前服务没有开启任务管理模式");
        }
    }

    @PutMapping("{id}")
    //@ApiOperation(value = "修改任务", notes = "operateEnum值:stop, resume, update")
    public void modifyJob(@PathVariable Integer id, @RequestBody QuartzJobDTO job, QuartzJobOperateEnum operateEnum) throws SchedulerException {
        checkService();
        service.modifyJob(id, operateEnum, job);
    }

    @DeleteMapping("{id}")
    //@ApiOperation(value = "删除任务")
    public void removeJob(@PathVariable Integer id) throws SchedulerException {
        checkService();
        service.removeJob(id);
    }
}

至此,还需要一个真正被执行的job

package com.milla.study.netbase.expert.quartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * @Package: com.milla.study.netbase.expert.quartz.job
 * @Description: <定时任务>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 18:58
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 18:58
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public class ExampleJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        //此处是需要定时执行的业务
        System.out.println("就做个打印吧");
    }
}

 此时可以写单元测试,或者是在controller中增加一个新方法模拟下

    @GetMapping("test")
    @ApiOperation(value = "测试增加任务")
    public void test(ReportQueryBO query) throws SchedulerException, ClassNotFoundException {
                QuartzJobDTO job = new QuartzJobDTO();
        job.setBeanClass(PumpReportJob.class.getName());
        job.setCronExpression("0/10 * * * * ?");
        job.setJobName("test");
        job.setJobGroup(UUIDUtils.randomUUID());
        job.setDescription("修改描述");
        job.setCreateTime(new Date());
        job.setCreator("Milla");
        job.setModifier("Milla's");
        managerService.addJob(job);
    }

这样这套完整的流程就基本上可以了。但是,一般情况都是将任务在数据库中配置好,在启动的时候加载所有需要指定的任务,所以需要一个初始化任务的类

package com.milla.study.netbase.expert.quartz.service;

import org.quartz.SchedulerException;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service
 * @Description: <初始化任务>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:38
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:38
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public interface QuartzJobService {
    void initSchedule() throws SchedulerException, ClassNotFoundException;
}

默认实现类 

package com.milla.study.netbase.expert.quartz.service.impl;

import com.milla.study.netbase.expert.quartz.service.QuartzJobService;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service.impl
 * @Description: <为了防止注入异常增加一个默认实现>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:39
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:39
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Service("default")
public class QuartzJobServiceImpl implements QuartzJobService {

    @Override
    public void initSchedule() throws SchedulerException, ClassNotFoundException {
    }
}

需要增加一个入口执行该初始化类

package com.milla.study.netbase.expert.quartz.listener;

import com.milla.study.netbase.expert.quartz.service.QuartzJobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Package: com.milla.study.netbase.expert.quartz.listener
 * @Description: <启动的时候执行>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:38
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:38
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Component
@Order(value = 1)
public class QuartzJobInitListener implements CommandLineRunner {
    
    @Autowired
    //所有实现初始化的接口都注入进来,然后遍历执行
    Map<String, QuartzJobService> scheduleJobServiceMap;

    @Override
    public void run(String... arg0) throws Exception {
        if (scheduleJobServiceMap == null || scheduleJobServiceMap.isEmpty()) {
            return;
        }
        Set<Map.Entry<String, QuartzJobService>> entries = scheduleJobServiceMap.entrySet();
        Iterator<Map.Entry<String, QuartzJobService>> it = entries.iterator();
        for (; it.hasNext(); ) {
            Map.Entry<String, QuartzJobService> next = it.next();
            //为防止报错,先给一个默认实现
            if ("default".equals(next.getKey())) {
                continue;
            }
            QuartzJobService service = next.getValue();
            service.initSchedule();
        }
    }

}

微服务中,可以将每个服务中对应的任务分别启动

服务一

package com.milla.study.netbase.expert.quartz.service.impl;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobStateEnum;
import com.milla.study.netbase.expert.quartz.mapper.QuartzJobDTOMapper;
import com.milla.study.netbase.expert.quartz.service.QuartzJobService;
import com.milla.study.netbase.expert.quartz.util.QuartzManager;
import org.apache.commons.collections4.CollectionUtils;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service.impl
 * @Description: <启动的时候加载加载在运行状态的任务并启动>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:39
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:39
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Service("report")
public class ExampleQuartzJobOneInitServiceImpl implements QuartzJobService {
    @Autowired
    private QuartzManager quartzUtil;
    @Autowired
    private QuartzJobDTOMapper mapper;

    @Override
    public void initSchedule() throws SchedulerException, ClassNotFoundException {
        // 获取所有报告的定时任务
        List<QuartzJobDTO> jobList = mapper.selectJobByGroup("report");
        if (CollectionUtils.isEmpty(jobList)) {
            return;
        }
        for (QuartzJobDTO job : jobList) {
            if (QuartzJobStateEnum.RUNNING.getCode().equals(job.getJobStatus())) {
                quartzUtil.addJob(job);
            }
        }
    }
}

服务二 

package com.milla.study.netbase.expert.quartz.service.impl;

import com.milla.study.netbase.expert.quartz.dto.QuartzJobDTO;
import com.milla.study.netbase.expert.quartz.enums.QuartzJobStateEnum;
import com.milla.study.netbase.expert.quartz.mapper.QuartzJobDTOMapper;
import com.milla.study.netbase.expert.quartz.service.QuartzJobService;
import com.milla.study.netbase.expert.quartz.util.QuartzManager;
import org.apache.commons.collections4.CollectionUtils;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Package: com.milla.study.netbase.expert.quartz.service.impl
 * @Description: <启动的时候加载加载在运行状态的任务并启动>
 * @Author: MILLA
 * @CreateDate: 2020/5/12 19:39
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/5/12 19:39
 * @UpdateRemark: <>
 * @Version: 1.0
 */
@Service("report")
public class ExampleQuartzJobTwoInitServiceImpl implements QuartzJobService {
    @Autowired
    private QuartzManager quartzUtil;
    @Autowired
    private QuartzJobDTOMapper mapper;

    @Override
    public void initSchedule() throws SchedulerException, ClassNotFoundException {
        // 获取所有报告的定时任务
        List<QuartzJobDTO> jobList = mapper.selectJobByGroup("report");
        if (CollectionUtils.isEmpty(jobList)) {
            return;
        }
        for (QuartzJobDTO job : jobList) {
            if (QuartzJobStateEnum.RUNNING.getCode().equals(job.getJobStatus())) {
                quartzUtil.addJob(job);
            }
        }
    }
}

 Ps:表达式还需要进行学习下

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。 Quartz的优势: 1、Quartz是一个任务调度框架(库),它几乎可以集成到任何应用系统中。 2、Quartz是非常灵活的,它让您能够以最“自然”的方式来编写您的项目的代码,实现您所期望的行为 3、Quartz是非常轻量级的,只需要非常少的配置 —— 它实际上可以被跳出框架来使用,如果你的需求是一些相对基本的简单的需求的话。 4、Quartz具有容错机制,并且可以在重启服务的时候持久化(”记忆”)你的定时任务,你的任务也不会丢失。 5、可以通过Quartz,封装成自己的分布式任务调度,实现强大的功能,成为自己的产品。6、有很多的互联网公司也都在使用Quartz。比如美团 Spring是一个很优秀的框架,它无缝的集成了Quartz简单方便的让企业级应用更好的使用Quartz进行任务的调度。   课程说明:在我们的日常开发中,各种大型系统的开发少不了任务调度,简单的单机任务调度已经满足不了我们的系统需求,复杂的任务会让程序猿头疼, 所以急需一套专门的框架帮助我们去管理定时任务,并且可以在多台机器去执行我们的任务,还要可以管理我们的分布式定时任务。本课程从Quartz框架讲起,由浅到深,从使用到结构分析,再到源码分析,深入解析QuartzSpring+Quartz,并且会讲解相关原理, 让大家充分的理解这个框架和框架的设计思想。由于互联网的复杂性,为了满足我们特定的需求,需要对Spring+Quartz进行二次开发,整个二次开发过程都会进行讲解。Spring被用在了越来越多的项目中, Quartz也被公认为是比较好用的定时器设置工具,学完这个课程后,不仅仅可以熟练掌握分布式定时任务,还可以深入理解大型框架的设计思想。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值