添加定时任务
This commit is contained in:
parent
3053e71a42
commit
ade6432bf4
9
pom.xml
9
pom.xml
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.7.18</version>
|
<version>2.4.5</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.bonus</groupId>
|
<groupId>com.bonus</groupId>
|
||||||
|
|
@ -61,6 +61,13 @@
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Quartz -->
|
||||||
|
<!-- Spring Boot Quartz Starter -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.bonus.emergencyrap.constant;
|
||||||
/**
|
/**
|
||||||
* 任务调度通用常量
|
* 任务调度通用常量
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author bonus
|
||||||
*/
|
*/
|
||||||
public class ScheduleConstants
|
public class ScheduleConstants
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.bonus.emergencyrap.task.config;
|
||||||
|
|
||||||
|
|
||||||
|
import org.quartz.Scheduler;
|
||||||
|
import org.quartz.spi.JobFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||||
|
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class QuartzConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JobFactory jobFactory() {
|
||||||
|
return new SpringBeanJobFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
|
||||||
|
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
|
||||||
|
schedulerFactoryBean.setJobFactory(jobFactory);
|
||||||
|
|
||||||
|
// 配置Quartz使用内存存储
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty("org.quartz.scheduler.instanceName", "MyScheduler");
|
||||||
|
properties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
|
||||||
|
properties.setProperty("org.quartz.jobStore.class", "org.quartz.simpl.RAMJobStore");
|
||||||
|
properties.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
|
||||||
|
properties.setProperty("org.quartz.threadPool.threadCount", "5");
|
||||||
|
|
||||||
|
schedulerFactoryBean.setQuartzProperties(properties);
|
||||||
|
return schedulerFactoryBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws Exception {
|
||||||
|
return schedulerFactoryBean.getScheduler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.bonus.emergencyrap.task.job;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.bonus.emergencyrap.constant.TextConstants;
|
||||||
|
import com.bonus.emergencyrap.utils.TextFileUtils;
|
||||||
|
import com.bonus.emergencyrap.utils.UploadFile;
|
||||||
|
import com.bonus.emergencyrap.vo.TaskVo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.Job;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行任务定时器
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class ActuatorJob implements Job {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ActuatorJob.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
log.info(context.getTrigger().getJobDataMap().get("taskId").toString());
|
||||||
|
String taskId = context.getTrigger().getJobDataMap().get("taskId").toString();
|
||||||
|
//文件进行解析
|
||||||
|
String filePtah= UploadFile.getFilePath(TextConstants.TASK);
|
||||||
|
Map<String,String> map= TextFileUtils.readFileMaps(filePtah);
|
||||||
|
TaskVo vo= JSON.parseObject(map.get(taskId), TaskVo.class);
|
||||||
|
System.err.println(vo.getTaskName());
|
||||||
|
logger.info("SampleJob 执行时间: {}", currentTime);
|
||||||
|
logger.info("任务执行器开始执行,执行任务id=="+vo.getTaskId()+"任务名称是=="+vo.getTaskName()+"执行时间=="+vo.getCorn());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.bonus.emergencyrap.task.job;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.bonus.emergencyrap.constant.TextConstants;
|
||||||
|
import com.bonus.emergencyrap.task.service.QuartzJobService;
|
||||||
|
import com.bonus.emergencyrap.utils.TextFileUtils;
|
||||||
|
import com.bonus.emergencyrap.utils.UploadFile;
|
||||||
|
import com.bonus.emergencyrap.vo.TaskVo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.Job;
|
||||||
|
import org.quartz.JobDataMap;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务扫描
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class ScanJob implements Job {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QuartzJobService service;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
try {
|
||||||
|
String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
System.err.println(currentTime);
|
||||||
|
String filePtah= UploadFile.getFilePath(TextConstants.TASK);
|
||||||
|
//文件是否存在
|
||||||
|
boolean isCz= TextFileUtils.exists(filePtah);
|
||||||
|
if(isCz){
|
||||||
|
//文件进行解析
|
||||||
|
Map<String,String> map=TextFileUtils.readFileMaps(filePtah);
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
TaskVo vo= JSON.parseObject(map.get(key), TaskVo.class);
|
||||||
|
String status=vo.getStatus();
|
||||||
|
//关闭直接删除
|
||||||
|
if("0".equals(status)){
|
||||||
|
service.deleteJob(vo);
|
||||||
|
}else{
|
||||||
|
//添加或者修改定时任务
|
||||||
|
service.addTask(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.err.println(context.getTrigger().getJobDataMap().get("taskId"));
|
||||||
|
log.info("定时任务扫描中scan....");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JobExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.bonus.emergencyrap.task.runner;
|
||||||
|
|
||||||
|
|
||||||
|
import com.bonus.emergencyrap.task.service.QuartzJobService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JobInitializer implements CommandLineRunner {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JobInitializer.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QuartzJobService quartzJobService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
try {
|
||||||
|
// 启动定时任务
|
||||||
|
quartzJobService.startSampleJob();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("启动定时任务失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.bonus.emergencyrap.task.service;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.bonus.emergencyrap.task.job.ActuatorJob;
|
||||||
|
import com.bonus.emergencyrap.task.job.ScanJob;
|
||||||
|
|
||||||
|
import com.bonus.emergencyrap.vo.TaskVo;
|
||||||
|
import org.quartz.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class QuartzJobService {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(QuartzJobService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Scheduler scheduler;
|
||||||
|
|
||||||
|
// 从配置文件读取简单间隔时间(秒)
|
||||||
|
@Value("${task.interval.seconds}")
|
||||||
|
private int taskIntervalSeconds;
|
||||||
|
|
||||||
|
public static String defeatGroup="EmergencyRap";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 固定任务 用来扫描全部的定时任务
|
||||||
|
public void startSampleJobWithSimpleTrigger() throws SchedulerException {
|
||||||
|
// 定义任务
|
||||||
|
JobDetail jobDetail = JobBuilder.newJob(ScanJob.class)
|
||||||
|
.usingJobData("taskId","555555555555")
|
||||||
|
.withIdentity("scanJob", "scanJobGroup")
|
||||||
|
.withDescription("扫描器")
|
||||||
|
.storeDurably()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 调度任务
|
||||||
|
if (!scheduler.checkExists(jobDetail.getKey())) {
|
||||||
|
// 从配置文件获取间隔时间,创建触发器
|
||||||
|
Trigger trigger = TriggerBuilder.newTrigger()
|
||||||
|
.withIdentity("scanJobTrigger", "scanJobGroup")
|
||||||
|
.usingJobData("taskId","555555555555")
|
||||||
|
.withDescription("扫描器")
|
||||||
|
.startNow()
|
||||||
|
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
|
||||||
|
.withIntervalInSeconds(taskIntervalSeconds)
|
||||||
|
.repeatForever())
|
||||||
|
.build();
|
||||||
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
logger.info("已启动任务扫描,间隔时间: {}秒", taskIntervalSeconds);
|
||||||
|
} else {
|
||||||
|
logger.info("任务已存在,无需重复启动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 使用cron表达式调度
|
||||||
|
public void addTask(TaskVo vo) throws SchedulerException {
|
||||||
|
// 定义任务
|
||||||
|
JobDetail jobDetail = JobBuilder.newJob(ActuatorJob.class)
|
||||||
|
.withIdentity(vo.getTaskId(), defeatGroup)
|
||||||
|
.withDescription("Cron定时任务")
|
||||||
|
.storeDurably()
|
||||||
|
.build();
|
||||||
|
// 调度任务
|
||||||
|
if (!scheduler.checkExists(jobDetail.getKey())) {
|
||||||
|
Trigger trigger = TriggerBuilder.newTrigger()
|
||||||
|
.withIdentity(vo.getTaskId(), defeatGroup)
|
||||||
|
.usingJobData("taskId",vo.getTaskId())
|
||||||
|
.withDescription(vo.getCorn())
|
||||||
|
.startNow()
|
||||||
|
.withSchedule(CronScheduleBuilder.cronSchedule(vo.getCorn()))
|
||||||
|
.build();
|
||||||
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
logger.info("已启动Cron任务,表达式: {}", vo.getCorn());
|
||||||
|
} else {
|
||||||
|
updateJobTime(vo);
|
||||||
|
logger.info("Cron任务已存在,进行定时任务时间更新");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 启动示例任务
|
||||||
|
public void startSampleJob() throws SchedulerException {
|
||||||
|
// 可以根据需要选择启动哪种类型的任务
|
||||||
|
startSampleJobWithSimpleTrigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暂停任务
|
||||||
|
public void pauseJob(String jobName, String jobGroup) throws SchedulerException {
|
||||||
|
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
|
||||||
|
if (scheduler.checkExists(jobKey)) {
|
||||||
|
scheduler.pauseJob(jobKey);
|
||||||
|
logger.info("已暂停任务: {}:{}", jobGroup, jobName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复任务
|
||||||
|
public void resumeJob(String jobName, String jobGroup) throws SchedulerException {
|
||||||
|
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
|
||||||
|
if (scheduler.checkExists(jobKey)) {
|
||||||
|
scheduler.resumeJob(jobKey);
|
||||||
|
logger.info("已恢复任务: {}:{}", jobGroup, jobName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除任务
|
||||||
|
public void deleteJob(TaskVo vo) throws SchedulerException {
|
||||||
|
JobKey jobKey = JobKey.jobKey(vo.getTaskId(), defeatGroup);
|
||||||
|
if (scheduler.checkExists(jobKey)) {
|
||||||
|
scheduler.deleteJob(jobKey);
|
||||||
|
logger.info("已删除任务: {}:{}", defeatGroup, vo.getTaskId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除任务
|
||||||
|
public void deleteJob(String jobName, String jobGroup) throws SchedulerException {
|
||||||
|
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
|
||||||
|
if (scheduler.checkExists(jobKey)) {
|
||||||
|
scheduler.deleteJob(jobKey);
|
||||||
|
logger.info("已删除任务: {}:{}", jobGroup, jobName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新当前正在运行的任务的cron时间
|
||||||
|
* @param
|
||||||
|
* @param
|
||||||
|
*/
|
||||||
|
private void updateJobTime(TaskVo vo) throws SchedulerException {
|
||||||
|
// 获取当前触发器
|
||||||
|
TriggerKey triggerKey = TriggerKey.triggerKey(vo.getTaskId(), defeatGroup);
|
||||||
|
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||||
|
String oldTime = cronTrigger.getCronExpression();
|
||||||
|
if (!oldTime.equalsIgnoreCase(vo.getCorn())) {
|
||||||
|
logger.info("定时任务已更新old和新的定时任务: {}:{}:{}", vo.getTaskName(),oldTime,vo.getCorn() );
|
||||||
|
Trigger trigger = TriggerBuilder.newTrigger()
|
||||||
|
.withIdentity(vo.getTaskId(), defeatGroup)
|
||||||
|
.usingJobData("taskId",vo.getTaskId())
|
||||||
|
.withDescription(vo.getCorn())
|
||||||
|
.startNow()
|
||||||
|
.withSchedule(CronScheduleBuilder.cronSchedule(vo.getCorn()))
|
||||||
|
.build();
|
||||||
|
//重置对应的job
|
||||||
|
scheduler.rescheduleJob(triggerKey, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新简单任务的执行间隔
|
||||||
|
public void refreshSimpleJob(String jobName, String jobGroup, int newIntervalSeconds) throws SchedulerException {
|
||||||
|
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
|
||||||
|
if (!scheduler.checkExists(jobKey)) {
|
||||||
|
throw new SchedulerException("任务不存在: " + jobGroup + ":" + jobName);
|
||||||
|
}
|
||||||
|
// 获取当前触发器
|
||||||
|
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||||
|
Trigger oldTrigger = scheduler.getTrigger(triggerKey);
|
||||||
|
|
||||||
|
// 创建新的触发器
|
||||||
|
Trigger newTrigger = TriggerBuilder.newTrigger()
|
||||||
|
.withIdentity(triggerKey)
|
||||||
|
.forJob(jobKey)
|
||||||
|
.startNow()
|
||||||
|
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
|
||||||
|
.withIntervalInSeconds(newIntervalSeconds)
|
||||||
|
.repeatForever())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 替换触发器
|
||||||
|
scheduler.rescheduleJob(triggerKey, newTrigger);
|
||||||
|
logger.info("已刷新简单任务 [{}:{}] 的执行间隔为 {} 秒",
|
||||||
|
jobGroup, jobName, newIntervalSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -93,5 +93,15 @@ public class TaskVo {
|
||||||
*/
|
*/
|
||||||
private String isLogin;
|
private String isLogin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 关闭 1 启用
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
/**
|
||||||
|
* 定时任务表达式
|
||||||
|
*/
|
||||||
|
private String corn;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ token:
|
||||||
# 令牌有效期(默认30分钟)
|
# 令牌有效期(默认30分钟)
|
||||||
expireTime: 30
|
expireTime: 30
|
||||||
|
|
||||||
|
task:
|
||||||
|
interval:
|
||||||
|
seconds: 60
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue