常用工具类系列(一)Quartz定时任务

前言

定时任务对于java开发人员来说比较常用,但是看网上说的都是含含糊糊,有也不是我想要的,还是自己写一个,比较实在。


一、Quartz是什么?

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.3.2。

简单说:就是对Spring自带的定时任务Scheduled又进行了一次封装,变得更完善了,更好的适用于业务得场景

开发文档URL:Quartz定时任务开发文档

二、Quartz能做什么?

常见开发场景:

  1. 每个月15号定时还花呗,借呗。
  2. 每年女朋友生日定时发送一条祝福短信。
  3. 每隔一个小时,提醒自己出去走走,提醒自己少脱发。
  4. 创建支付订单,用户xx小时未进行支付,修改订单状态为超时时间。
  5. 创建拍卖活动,到固定时间,修改活动状态为开启或者关闭。

简单说:
1.有规律的重复做某事 :

  • (一)每年/每月/每日/做某事
  • (二)间隔多少 时/分/秒做某事

2.指定某一时刻做某事

  • (一)2020年10月10日 10点10分10秒 给喜欢的人发一条短信

三、Quartz怎么使用?

1.引入依赖

代码如下(示例):

        <!--定时任务依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

2.配置application.yml

自行修改相关配置(需要下载定时任务11张相关数据表,网上随便搜就能下载):
下载地址:定时任务十一个常用数据库表

#定时任务持久化设置
spring:
  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler #调度器实例名称
            instanceId: AUTO #调度器实例编号自动生成
          jobStore: #持久化方式配置
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #持久化方式配置数据驱动,MySQL数据库
            tablePrefix: QRTZ_ #quartz相关数据表前缀名
            isClustered: false #开启分布式部署
            clusterCheckinInterval: 10000 #分布式节点有效性检查时间间隔,单位:毫秒
            useProperties: false #配置是否使用
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool #线程池实现类
            threadCount: 10 #执行最大并发线程数量
            threadPriority: 5 #线程优先级
            threadsInheritContextClassLoaderOfInitializingThread: true #配置是否启动自动加载数据库内的定时任务,默认true
    #数据库方式
    job-store-type: jdbc

2.封装定时任务工具类

package com.ruoyi.common.utils.quartz;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @program: moonShine
 * @description: 定时任务管理工具类
 * @author: Sun
 * @create: 2020-03-05 13:37
 **/
@Component
public class QuartzManagerUtil {
    //设置日期格式
    private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 获取当前系统时间
     */
    public  String getCurrentDate(){
        return format.format(new Date());
    }
    /**
     * 将String时间转化为系统Date 时间
     * @param time
     * @return
     */
    public  Date toDateTime(String time){
        Date date= new Date();
        try {
            date= format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }


    /**
     * 比较两个时间的大小
     * date1小于date2返回-1,date1大于date2返回1,相等返回0
     * @param date1
     * @param date2
     * @return
     */
    public  Integer compareToTime1AndTime2 (String date1,String date2){
        Date time1= toDateTime(date1);
        Date time2= toDateTime(date2);
        return time1.compareTo(time2);
    }


    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void startScheduler() {
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }


    /**
     *
     * 方法名称:添加一个定时任务在 指定时间执行一次
     *
     * 功能描述:
     * 〈〉
     *
     * @param jobClass 任务实现类
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     * @param jobStartTime 任务执行的时间
     * @param jobData 传递数据 参数
     * @return : void
     * @author : Sun
     * @date : 2020/3/4
     */
    public void addJobAtTime(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, Date jobStartTime, Map jobData) {
        try {
            // 任务名称和组构成任务key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // 设置job参数
            if(jobData!= null && jobData.size()>0){
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // 使用simpleTrigger规则
            Trigger trigger  = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    .startAt(jobStartTime)
                    .build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }




    /**
     * 增加一个job
     *
     * @param jobClass
     *            任务实现类
     * @param jobName
     *            任务名称
     * @param jobGroupName
     *            任务组名
     * @param jobTime
     *            时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes
     *            运行的次数 (<0:表示不限次数)
     * @param jobData
     *            参数
     */
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                       int jobTimes, Map jobData) {
        try {
            // 任务名称和组构成任务key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // 设置job参数
            if(jobData!= null && jobData.size()>0){
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // 使用simpleTrigger规则
            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();
            }
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加一个job
     *
     * @param jobClass
     *            任务实现类
     * @param jobName
     *            任务名称(建议唯一)
     * @param jobGroupName
     *            任务组名
     * @param jobTime
     *            时间表达式 (如:0/5 * * * * ? )
     * @param jobData
     *            参数
     */
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData) {
        try {
            // 创建jobDetail实例,绑定Job实现类
            // 指明job的名称,所在组的名称,以及绑定job类
            // 任务名称和组构成任务key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // 设置job参数
            if(jobData!= null && jobData.size()>0){
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // 定义调度触发规则
            // 使用cornTrigger规则
            // 触发器key
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();
            // 把作业和触发器注册到任务调度中
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改 一个job的 时间表达式
     *
     * @param jobName
     * @param jobGroupName
     * @param jobTime
     */
    public void updateJob(String jobName, String jobGroupName, String jobTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            // 重启触发器
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除任务一个job
     *
     * @param jobName
     *            任务名称
     * @param jobGroupName
     *            任务组名
     */
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            scheduler.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public void pauseJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public void resumeJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立即执行一个job
     *
     * @param jobName
     * @param jobGroupName
     */
    public void runAJobNow(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     */
    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) {
                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.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();
        }
        return jobList;
    }

    /**
     * 获取所有正在运行的job
     * @return
     */
    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.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();
        }
        return jobList;
    }
}

3.创建定时任务示例

  • 示例代码

@Api("测试定时任务api接口")
@RestController
@RequestMapping("/api/quartz")
public class QuartzTest {

    @Autowired
    QuartzManagerUtil quartzManagerUtil;
    @PostMapping("/testQuartz")
    public void testQuartz()
    {
        //添加定时任务
        //创建活动开启定时任务
        //job名称 唯一
        String jobName= QuartzJobNameConfig.getTestJobName();
        //job开启组  可不唯一
        String jobGroupName= QuartzGroupNameConfig.TEST_JOB_GROUP_CANCLE_ORDER;
        //任务执行时间
        Date jobData = new Date();
        //添加参数
        Map<String,Object> dataMap=new HashMap<>();
        dataMap.put("param_id",111);
        //添加任务前 先执行删除操作,确保新增成功
        quartzManagerUtil.deleteJob(jobName,jobGroupName);
        //添加定时任务
    	quartzManagerUtil.addJobAtTime(TestJobClass.class,jobName,jobGroupName,jobData,dataMap);

    }

}
  • 实际处理业务类
/**
 * @description: 测试任务执行类
 * @author: Sun
 * @create: 2020-11-30 11:34
 **/
@Component
public class TestJobClass extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {

            JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
            //获取参数
            Integer paramId=Integer.valueOf(jobDataMap.get("param_id").toString());
            //执行业务逻辑
            System.out.println("执行业务逻辑"+paramId);
        }
        catch (Exception e){
            e.printStackTrace();
        }

    }
}

4.可能用到工具类

  • 订时任务job名称(唯一)
/**
 * @description: 定时任务Job名称
 * @author: Sun
 * @create: 2020-11-30 11:10
 **/

public class QuartzJobNameConfig {

    //job 名称前缀
    private static final  String JOB_NAME="TEST_JOB";

    //格式化名称
    private static final SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 生成唯一的 job名称
     */
    public static String getTestJobName() {
        //生成拍卖job名称
        return JOB_NAME + sdf1.format(new Date()) + (1 + (int) (Math.random() * 10000));
    }
}
  • 订时任务job组名

/**
 * @description: 定时任务(任务组)名称配置
 * @author: Sun
 * @create: 2020-11-30 11:11
 **/

public class QuartzGroupNameConfig {

    //测试组名称  取消订单
    public static final  String TEST_JOB_GROUP_CANCLE_ORDER="CANCEL_ORDER";

}

总结

这就是quartz 定时任务的基本工具类封装,应该可以完成大部分的业务场景。喜欢的可以点个赞

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颜良配情深

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值