添加定时任务

This commit is contained in:
haozq 2025-09-25 15:11:01 +08:00
parent 3053e71a42
commit ade6432bf4
9 changed files with 376 additions and 2 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bonus</groupId>
@ -61,6 +61,13 @@
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Quartz -->
<!-- Spring Boot Quartz Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>

View File

@ -3,7 +3,7 @@ package com.bonus.emergencyrap.constant;
/**
* 任务调度通用常量
*
* @author ruoyi
* @author bonus
*/
public class ScheduleConstants
{

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -93,5 +93,15 @@ public class TaskVo {
*/
private String isLogin;
/**
* 0 关闭 1 启用
*/
private String status;
/**
* 定时任务表达式
*/
private String corn;
}

View File

@ -62,6 +62,10 @@ token:
# 令牌有效期默认30分钟
expireTime: 30
task:
interval:
seconds: 60