基于注解@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){
//处理逻辑
}
}