springBoot下使用quartz定时任务;动态修改任务执行时间

先上依赖

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

新建一个自己的Job类,待会触发器执行的就是这个类重写的QuartzJobBean下的executeInternal方法

里面可以通过spring注入业务类,这样就可以执行业务逻辑了

package com.fchan.layui.quzrtzForSpring;

import com.fchan.layui.quartz.TestJobDetailService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

@Component
public class HiJob extends QuartzJobBean {
	
	//自己的业务类,我在里面就打印输出了一下字符串:"开始处理业务了"
    @Autowired
    private TestJobDetailService testJobDetailService;


    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        testJobDetailService.doJob();
        System.out.println("    Hi! :" + context.getJobDetail().getKey());
    }
}

配置类,配置Jobdetail(配置执行哪个Job)和Trigger触发器(定义cron的bean)

Jobdetail->Job->业务类

package com.fchan.layui.quzrtzForSpring;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuzrtzForSpringConfig {

    @Bean
    public JobDetail myJobDetail(){
        JobDetail jobDetail = JobBuilder.newJob(HiJob.class)
                //任务名和任务组别
                .withIdentity("myJobName","myJobGroup")
                //JobDataMap可以给任务execute传递参数
                .usingJobData("job_param","job_param1")
                .storeDurably()
                .build();
        return jobDetail;
    }

    @Bean
    public Trigger myTrigger(){
        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(myJobDetail())
                //触发器名,触发器所在组
                .withIdentity("myTrigger1","myTriggerGroup1")
                .usingJobData("job_trigger_param","job_trigger_param1")
                .startNow()
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ? 2020"))
                .build();
        return trigger;
    }

}

然后跑起来就可以在控制台看到业务类中打印输出的内容了
在这里插入图片描述

动态修改任务执行时间

动态执行的时候就不能直接写死时间了。
quzrtz中的定时任务分为这几大块:

  • jobDetail:描述实际执行任务的class
  • trigger:触发器,定义执行时间
  • scheduler:关联触发器和任务

所以要动态修改时间,就要修改触发器中的时间,然后重新关联任务。

代码demo

实际执行任务class

package com.fchan.business.cron;

import com.fchan.business.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import javax.annotation.Resource;
import java.time.LocalDateTime;

@Slf4j
public class MailTask extends QuartzJobBean {

    @Resource
    ISysUserService iSysUserService;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("开始执行邮件任务" + LocalDateTime.now());
    }
}
package com.fchan.business.cron;

import lombok.Data;

/**
 * 定义时间和实际执行任务的class
 */

@Data
public class QuartzBean {

    /** 任务id */
    private String  id;

    /** 任务名称 */
    private String jobName;

    /** 任务执行类 */
    private String jobClass;

    /** 任务状态 启动还是暂停*/
    private Integer status;

    /** 任务运行时间表达式 */
    private String cronExpression;


}

新增/暂停/修改/删除定时任务

package com.fchan.business.utils;

import com.fchan.business.cron.QuartzBean;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;

@Slf4j
public class CronUtil {


    /**
     * 创建一个定时任务
     * @param scheduler
     * @param quartzBean
     */
    public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean){
        try {

            //反射获取实际执行任务的class
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());

            //构建任务信息,实际执行的任务类
            JobDetail jobDetail = JobBuilder
                                        .newJob(jobClass)
                                        //jobName需要保证唯一
                                        .withIdentity(quartzBean.getJobName())
                                        .build();

            //设置执行方式为cron
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
                    .cronSchedule(quartzBean.getCronExpression())
                    //阻塞的过期任务立即执行
                    .withMisfireHandlingInstructionFireAndProceed();

            //关联触发器和cron执行器
            CronTrigger cronTrigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(quartzBean.getJobName())
                    .withSchedule(cronScheduleBuilder)
                    .build();



            //检查任务是否过期
            Date nextFireTime = cronTrigger.getFireTimeAfter(new Date());
            if(Objects.isNull(nextFireTime)){
                log.info("任务已过期,job:{}", quartzBean);
                return;
            }

            //按照cron时间开始运行任务,并且时间已经过期则创建时会报错,提示过期
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (ClassNotFoundException | SchedulerException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * 更新当前正在运行的任务的cron时间
     * @param scheduler
     * @param quartzBean
     */
    public static void updateJobTime(Scheduler scheduler, QuartzBean quartzBean){

        //build触发key
        TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());

        String cronExpression = quartzBean.getCronExpression();

        //build新的cron执行器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        try {

            //获取当前正在运行的触发器
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            if(Objects.isNull(cronTrigger)){
                log.error("未找到触发器,jobName:{}", quartzBean.getJobName());
                return;
            }

            //根据新的执行器重新关联触发器
            cronTrigger = cronTrigger
                                .getTriggerBuilder()
                                .withIdentity(triggerKey)
                                .withSchedule(cronScheduleBuilder)
                                .build();

            log.info("重置了任务时间" + LocalDateTime.now());

            //重置对应的job
            scheduler.rescheduleJob(triggerKey, cronTrigger);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 暂停任务
     * @param scheduler
     * @param jobName
     */
    public static void pauseJob(Scheduler scheduler, String jobName){
        JobKey jobKey = JobKey.jobKey(jobName);

        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 恢复暂停的任务
     * @param scheduler
     * @param jobName
     */
    public static void resumeJob(Scheduler scheduler, String jobName){
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 删除任务
     * @param scheduler
     * @param jobName
     */
    public static void deleteJob(Scheduler scheduler, String jobName){
        JobKey jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值