Springboot2模块系列:Quartz(定时任务)

1 Quartz简介

Quartz是执行定时任务的框架,由开源组织OpenSymphony在Job scheduling领域的开源项目,完全由java开发.
组成:

  • Job,JobDetail
    Job具体的业务逻辑类,JobDetail业务实例,实现多任务.
  • Trigger
    JobDetail触发器,即执行任务的触发条件(设定的时间,时间间隔和执行次数).包括SimpleTrigger和CronTrigger,SimpleTrigger为简单触发条件,如执行时间和执行次数,CronTrigger可进一步设定执行周期,年月日时段.
  • Scheduler
    调度器,通过触发器执行业务.

2 组件功能

2.1 Job

Job是Quartz中的一个接口,只有execute方法,在这个方法中编写业务逻辑.

public interface Job{
	void execute(JobExecutionContext var1) throws JobExecutionException;
}

2.2 JobDetail

可理解为Job的实例,每调用一个Job,通过JobDetail创建一个新的实例,Scheduler对JobDetail进行调度,可实现多定时任务.

  • JobBuilder
    实例化JobDetail,创建新的Job执行任务.

2.3 JobExecutionContext

包含Job的详细参数,当Scheduler执行一个Job时,将JobExecutionContext传递给Job中的execute方法.

2.4 Trigger

触发器,满足触发器条件,执行任务.

  • TriggerBuilder
    实例化触发器.
  • SimpleTrigger
    触发时间规则设定器,包括指定时间段内执行任务的次数.
  • CronTrigger
    触发时间规则设定器,基于日历的作业调度,可指定执行日期,日历规则:
秒 分 小时 日 月 周 年
序号时间字段允许值允许特殊字符
10-59-*/
20-59-*/
3小时0-23-*/
41-31-*?/LWC
5月份1-12或JAN-DEC-*/
61-7或SUN-SAT-*?/LC#
7(可选)1970-2099-*/

3 Usage

3.1 pom.xml

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

3.2 定时任务操作

package com.prjname.service;

import java.util.Map;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
public class TimerService{
    @Autowired 
    private Scheduler scheduler;
        
    public String buildTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        String timeCycle = taskInfos.get("taskTimeCycle").toString();
        String classNameStr = taskInfos.get("className").toString();
        Class className = Class.forName(classNameStr);
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(timeCycle);
        JobDetail jobDetail = JobBuilder.newJob(className)
                                        .withIdentity(name, group)
                                        .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                                        .withIdentity(name, group)
                                        .startNow()
                                        .withSchedule(scheduleBuilder)
                                        .build();
        scheduler.scheduleJob(jobDetail, trigger);
        return "新建并启动5秒的定时任务";
    }

    public String pauseTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.pauseJob(jobKey);
        return "暂停定时任务"+name;
    }

    public String resumeTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey= new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey); 
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.resumeJob(jobKey);
        return "恢复定时任务:"+name;
    }

    public String deleteTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.deleteJob(jobKey);
        return "删除定时任务:"+name;
    }
}

3.2.1 新建定时任务

public String buildTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        String timeCycle = taskInfos.get("taskTimeCycle").toString();
        String classNameStr = taskInfos.get("className").toString();
        Class className = Class.forName(classNameStr);
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(timeCycle);
        JobDetail jobDetail = JobBuilder.newJob(className)
                                        .withIdentity(name, group)
                                        .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                                        .withIdentity(name, group)
                                        .startNow()
                                        .withSchedule(scheduleBuilder)
                                        .build();
        scheduler.scheduleJob(jobDetail, trigger);
        return "新建并启动5秒的定时任务";
    }

3.2.2 停止定时任务

public String pauseTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.pauseJob(jobKey);
        return "暂停定时任务"+name;
    }

3.2.3 重启定时任务

public String resumeTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey= new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey); 
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.resumeJob(jobKey);
        return "恢复定时任务:"+name;
    }

3.2.4 删除定时任务

 public String deleteTimerTask(Map taskInfos) throws Exception{
        String name = taskInfos.get("taskName").toString();
        String group = taskInfos.get("taskGroup").toString();
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if(jobDetail == null){
            return "定时任务不存在";
        }
        scheduler.deleteJob(jobKey);
        return "删除定时任务:"+name;
    }

3.2.5 定时任务传参

新建定时任务时,可以传递参数,使用usingJobData属性,操作如下:

JobDetail jobDetail = JobBuilder.newJob(className)
                                        .withIdentity(name, group)
                                        .usingJobData("params", params)
                                        .build();

3.3 定时任务执行业务逻辑

该部分为定时任务定期执行的业务逻辑,本次以打印时间为例,每隔5秒,打印一次当前时间。

package com.prjname.timer;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class TestTimer extends QuartzJobBean{
    static Logger logger = LoggerFactory.getLogger(TestTimer.class);
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String time = sdf.format(date);
        logger.info("定时时间:{}",time);
    }
}

3.4 控制器

package com.prjname.controller;

import com.xhwl.service.TimerService;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin(origins="*", maxAge=3600)
@RestController
@RequestMapping("/api/v1")
public class TimerController{
    static Logger logger = LoggerFactory.getLogger(TimerController.class);
    @Autowired
    private TimerService timerService;

    @RequestMapping(value="/timer-task-creation", method=RequestMethod.POST)
    public Map createTimerTask(@RequestBody Map params){
        Map returnMap = new HashMap();
        try{
            String taskName = params.get("taskName").toString();
            String taskGroup = params.get("taskGroup").toString();
            String taskTimeCycle = params.get("taskCycle").toString();
            if(!taskName.equals("")|!taskGroup.equals("")|!taskTimeCycle.equals("")){
                Map<String, String> taskInfos = new HashMap<String, String>();
                taskInfos.put("taskName", taskName);
                taskInfos.put("taskGroup", taskGroup);
                taskInfos.put("taskTimeCycle", taskTimeCycle);
                taskInfos.put("className", "com.prjname.timer.TestTimer");
                String returnStr = timerService.startTimerTask(taskInfos);
                returnMap.put("code",200);
                returnMap.put("infos",returnStr);
                return returnMap;
            }else{
                returnMap.put("code",200);
                returnMap.put("infos","检查参数");
                return returnMap;
            }
            
        }catch(Exception e){
            e.printStackTrace();
        }
        returnMap.put("code",400);
        returnMap.put("infos","检查参数");
        return returnMap;
    }

    @RequestMapping(value="/timer-task-pause", method=RequestMethod.POST)
    public Map pauseTimerTask(@RequestBody Map params){
        Map returnMap = new HashMap();
        try{
            String taskName = params.get("taskName").toString();
            String taskGroup = params.get("taskGroup").toString();
            if(!taskName.equals("")|!taskGroup.equals("")){
                String returnStr = timerService.pauseTimerTask(params);
                returnMap.put("code", 200);
                returnMap.put("infos", returnStr);
                return returnMap;
            }else{
                returnMap.put("code", 400);
                returnMap.put("infos", "检查参数");
                return returnMap;
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return returnMap;
    }
}

【参考文献】
[1]https://www.jb51.net/article/160555.htm
[2]https://blog.csdn.net/noaman_wgs/article/details/80984873
[3]https://www.jianshu.com/p/056281e057b3
[4]https://www.cnblogs.com/knowledgesea/p/4705796.html
[5]https://www.cnblogs.com/bevis-byf/p/10087032.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天然玩家

坚持才能做到极致

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

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

打赏作者

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

抵扣说明:

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

余额充值