springboot 中动态实现定时任务

基于注解@Scheduled实现需在启动类配合 @EnableScheduling(开启定时任务)、@EnableAsync(开启异步任务)一起使用

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;

public class Quartz {

    /**
     * @Description: 每日凌晨初始化财务统计
     */
    @Async
    @Scheduled(cron = "0 0 0 * * ?")
    public void InitPaymentLog(){
    	//逻辑处理
    }
}

下面简单展示通过维护到数据库中动态实现的案例
定时任务用到的依赖包:

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

定时任务数据表结构:
在这里插入图片描述
项目启动扫描定时任务

import com.hrkj.scalp.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.security.KeyPair;
import java.util.List;

@Component
@Order(0) // 执行顺序,越小越先执行
public class MyCommandLineRunner implements CommandLineRunner {

    @Autowired
    private QuartzJobService quartzJobService;
    
    @Override
    public void run(String... args) throws Exception {
        // 生成秘钥对
        //KeyPair keyPair = RSAUtil.getKeyPair();
        // 获取私钥
        //String private_key = RSAUtil.getPrivateKey(keyPair);
        // 获取公钥
        //String public_key = RSAUtil.getPublicKey(keyPair);
        // 设置私钥
        //KeyManager.setPrivate_key(private_key);
        // 设置公钥
       // KeyManager.setPublic_key(public_key);
        quartzJobService.executeJob();
    }

}

业务逻辑的主要调用方法:

    @Autowired
    private Scheduler scheduler;

    /**
     * 项目启动读取数据库中的待执行订单定时任务进行启动
     */
    public void executeJob(){
        List<QuartzJob> list = this.list(new QueryWrapper<QuartzJob>()
        		.eq("status",0)
        		.and(c->c.ge("execute_time",new Date()).or().isNull("execute_time"))
        );
        if(list.size() == 0) return ;
        try {
       		// 启动调度器 此外还有.standy(挂起,可进行恢复),.shutdown(关闭,不可恢复)
            scheduler.start(); 
            for(QuartzJob job : list){
            	schedulerDelete(job.getJobName(),job.getIdentity());
            	execute(job,false);
        	}
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        log.info("===共加载到{}个待执行的定时任务===",list.size());
    }

    /**
     * 创建定时任务
     * @param job  任务信息
     * @param flag  是否添加入库
     */
    public String execute(QuartzJob job,boolean flag){
    	//任务类名即处理类在项目中的路径,例如我这里的jobName是com.xx.quartz.QuartzTaskRandom	
        String className = job.getJobName(); //对于不同的任务处理逻辑我这里使用了不同的处理类
        try {
        // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(className).getClass())
                    .withIdentity(className+job.getIdentity())
                    .usingJobData("params", job.getParams()) //任务使用参数
                    .build();
            // 执行表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(className+job.getIdentity()).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger); //绑定 并返回任务触发的时间
            if(flag){
                this.save(job); //保存入库
            }
        } catch (SchedulerException e) {
            return "创建定时任务失败";
        } catch (RuntimeException e) {
            return e.getMessage();
        }catch (Exception e) {
            return "后台找不到该类名:" + className;
        }
        return "";
    }


    /**
     * 删除定时任务
     * @param identity
     * @param className
     */
    public void schedulerDelete(String identity,String className) {
        try {
            String key = className+identity;
            scheduler.pauseTrigger(TriggerKey.triggerKey(key));//停止触发器
            scheduler.unscheduleJob(TriggerKey.triggerKey(key));//移除触发器  先停止再移除
            scheduler.deleteJob(JobKey.jobKey(key)); //最后再删除任务
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new JeecgBootException("删除定时任务失败");
        }
    }
    
    /**
     * 暂停定时任务
     * @param taskId
     * @throws SchedulerException
     */
    public void pause(String taskId,String className){
        try {
            scheduler.pauseJob(JobKey.jobKey(className+taskId));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    
    private static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }

任务逻辑处理类:

package com.xx.quartz;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * @ClassName QuartzTaskRandom.java
 * @Description 直播间指令执行方式:从指令指定设备中选择n台每间隔一定时间随机执行一次
 * @createTime 2021/02/19 19:48
 */
@Slf4j
@Async
public class QuartzTaskRandom implements Job {

    @Autowired
    private QuartzJobService quartzJobService;

    private String params; //接收创建任务时放入的params参数

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }


    @Override
    public void execute(JobExecutionContext context){
    	//处理逻辑
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值