1. 修改定时任务方式

This commit is contained in:
梁州 2025-04-22 10:19:06 +08:00
parent 88c5652faa
commit 2c65377f48
14 changed files with 648 additions and 15 deletions

View File

@ -26,6 +26,10 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->

View File

@ -0,0 +1,17 @@
package com.wms.constants.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 定时器定时类型
*/
@Getter
@AllArgsConstructor
public enum JobTimerTypeEnums {
SIMPLE(1, "简单任务"),
CRON(2, "cron表达式");
private final Integer type;
private final String description;
}

View File

@ -32,7 +32,6 @@ import java.util.*;
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@EnableAsync
public class JobComponent {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
@ -56,8 +55,7 @@ public class JobComponent {
* 向Wcs下发任务
* 每2秒执行一次
*/
@Scheduled(fixedDelay = 2000)
@Async
// @Scheduled(fixedDelay = 2000)
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendCommonTasks() {
if (isSendingCommonTask) {
@ -85,8 +83,7 @@ public class JobComponent {
* 向Wcs下发站台拣选出库任务
* 每2秒执行一次
*/
@Scheduled(fixedDelay = 2000)
@Async
// @Scheduled(fixedDelay = 2000)
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendPickOutTasks() {
if (isSendingPickOutTask) {
@ -113,8 +110,7 @@ public class JobComponent {
* 拣选任务
* 每2秒执行一次
*/
@Scheduled(fixedDelay = 2000)
@Async
// @Scheduled(fixedDelay = 2000)
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendPickTasks() {
if (isSendingPickTask) {
@ -161,7 +157,7 @@ public class JobComponent {
/**
* 创建工作
*/
@Scheduled(fixedDelay = 20000)
// @Scheduled(fixedDelay = 20000)
public void createWork() {
String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey());
if (StringUtils.isEmpty(createWork) || !createWork.equals("1")) {
@ -197,7 +193,7 @@ public class JobComponent {
/**
* 执行工作
*/
@Scheduled(fixedDelay = 20000)
// @Scheduled(fixedDelay = 20000)
public void doWork() {
String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey());
if (StringUtils.isEmpty(startWork) || !startWork.equals("1")) {
@ -228,8 +224,7 @@ public class JobComponent {
* 每天查询一次是否有过期记录
* 每天晚上10点执行一次
*/
@Scheduled(cron = "0 0 22 * * ?")
@Async
// @Scheduled(cron = "0 0 22 * * ?")
public void deleteOutOfDateData() {
// 删除日志数据
wmsJobService.deleteLogsRegularly();

View File

@ -0,0 +1,19 @@
package com.wms.quartz;
import com.wms.service.quartz_job.IJobService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* 定时任务启动类
*/
@Component
@RequiredArgsConstructor
public class JobStarter implements CommandLineRunner {
private final IJobService jobService;
@Override
public void run(String... args) {
jobService.initAllJobs();
}
}

View File

@ -0,0 +1,140 @@
package com.wms.quartz;
import com.wms.constants.enums.JobTimerTypeEnums;
import com.wms.quartz.config.JobBean;
import lombok.RequiredArgsConstructor;
import org.quartz.*;
import java.util.Objects;
/**
* 定时任务工具类
*/
@RequiredArgsConstructor
public class JobUtils {
/**
* 创建任务
* @param scheduler 调度器
* @param jobBean 任务信息
*/
public static void createJob(Scheduler scheduler, JobBean jobBean) {
try {
// 生成任务
JobDetail jobDetail = JobBuilder.newJob(jobBean.getJobClass())
.storeDurably()
.withIdentity(jobBean.getJobName())
.build();
// 生成触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withIdentity(jobBean.getJobName() + "_trigger");
if (Objects.equals(jobBean.getTimerType(), JobTimerTypeEnums.CRON.getType())) {
// cron
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(jobBean.getCronExpression()));
} else {
// 简单定时器
if (jobBean.getTimer() == null || jobBean.getTimer() < 100) {
triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(100).repeatForever());
} else {
triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(jobBean.getTimer()).repeatForever());
}
}
Trigger trigger = triggerBuilder.build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 暂停定时任务
* @param scheduler 调度器
* @param jobName 任务名
*/
public static void pauseJob(Scheduler scheduler, String jobName) {
try {
scheduler.pauseJob(JobKey.jobKey(jobName));
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 恢复定时任务
* @param scheduler 调度器
* @param jobName 任务名
*/
public static void resumeJob(Scheduler scheduler, String jobName) {
try {
scheduler.resumeJob(JobKey.jobKey(jobName));
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 删除定时任务
* @param scheduler 调度器
* @param jobName 任务名
*/
public static void deleteJob(Scheduler scheduler, String jobName) {
try {
scheduler.deleteJob(JobKey.jobKey(jobName));
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 立即执行一次任务
* @param scheduler 调度器
* @param jobName 任务名
*/
public static void runJobOnce(Scheduler scheduler, String jobName) {
try {
scheduler.triggerJob(JobKey.jobKey(jobName));
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 更新任务信息
* @param scheduler 调度器
* @param jobBean 任务信息
*/
public static void modifyJob(Scheduler scheduler, JobBean jobBean) {
try {
// 获取触发器唯一标识
TriggerKey triggerKey = TriggerKey.triggerKey(jobBean.getJobName() + "_trigger");
if (Objects.equals(jobBean.getTimerType(), JobTimerTypeEnums.CRON.getType())) {// cron
// 获取触发器唯一对象
CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 使用新cron表达式构建新的触发器
CronTrigger newTrigger = oldTrigger.getTriggerBuilder()
.withSchedule(CronScheduleBuilder.cronSchedule(jobBean.getCronExpression()))
.build();
// 调度器更新最新的触发器
scheduler.rescheduleJob(triggerKey, newTrigger);
} else {
// 获取触发器唯一对象
SimpleTrigger oldTrigger = (SimpleTrigger) scheduler.getTrigger(triggerKey);
// 使用新cron表达式构建新的触发器
SimpleTrigger newTrigger;
if (jobBean.getTimer() == null || jobBean.getTimer() < 100) {
newTrigger = oldTrigger.getTriggerBuilder()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(100).repeatForever())
.build();
} else {
newTrigger = oldTrigger.getTriggerBuilder()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(jobBean.getTimer()).repeatForever())
.build();
}
// 调度器更新最新的触发器
scheduler.rescheduleJob(triggerKey, newTrigger);
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,45 @@
package com.wms.quartz.config;
import jakarta.validation.constraints.Min;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.quartz.Job;
/**
* 定时任务配置类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JobBean {
/**
* 任务名
*/
private String jobName;
/**
* 任务类class
*/
private Class<? extends Job> jobClass;
/**
* cron表达式
*/
private String cronExpression;
/**
* 普通定时器---单位毫秒
*/
@Min(value = 100, message = "定时器任务间隔不能小于100ms")
private Integer timer;
/**
* timer类型
* 1: 普通定时器
* 2cron
*/
private Integer timerType;
/**
* 任务状态
* 1启用
* 0未启用
*/
private Integer jobStatus;
}

View File

@ -0,0 +1,47 @@
package com.wms.quartz.job_executor;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.service.business.IWmsJobService;
import com.wms.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import static com.wms.config.InitLocalConfig.configMap;
/**
* 普通任务发送定时器类
*/
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class CommonTaskSender implements Job {
/**
* WMS定时任务服务
*/
private final IWmsJobService wmsJobService;
/**
* 执行
* @param jobExecutionContext 执行文本
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void execute(JobExecutionContext jobExecutionContext) {
try {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
return;
}
// 发送正常任务
wmsJobService.sendCommonTasks();
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}

View File

@ -0,0 +1,30 @@
package com.wms.quartz.job_executor;
import com.wms.service.business.IWmsJobService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class DataClearExecutor implements Job {
/**
* WMS定时任务服务
*/
private final IWmsJobService wmsJobService;
/**
* 执行定时清理数据
* @param jobExecutionContext 运行上下文
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) {
// 删除日志数据
wmsJobService.deleteLogsRegularly();
// 删除记录数据
wmsJobService.deleteRecordsRegularly();
}
}

View File

@ -0,0 +1,104 @@
package com.wms.quartz.job_executor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.entity.table.Stand;
import com.wms.service.StandService;
import com.wms.service.business.IWorkService;
import com.wms.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import static com.wms.config.InitLocalConfig.configMap;
import static com.wms.utils.StringUtils.convertJsonString;
/**
* 卡特工作定时任务
*/
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class KateWorkExecutor implements Job {
/**
* 站台服务
*/
private final StandService standService;
/**
* 工作服务
*/
private final IWorkService workService;
/**
* 定时任务执行
* @param jobExecutionContext 定时任务执行上下文
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) {
// 创建工作
createWork();
// 执行工作
doWork();
}
/**
* 创建工作
*/
public void createWork() {
String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey());
if (StringUtils.isEmpty(createWork) || !createWork.equals("1")) {
return;
}
// 判断当前时间是否在740到2340之间
LocalDateTime now = LocalDateTime.now();
if (now.isBefore(LocalDateTime.of(now.toLocalDate(), LocalTime.of(7, 40))) || now.isAfter(LocalDateTime.of(now.toLocalDate(), LocalTime.of(23, 40)))) {
return;
}
try {
workService.createTempWorkFlows();
} catch (Exception e) {
log.error("创建当日工作发生错误:{}", e.getMessage());
}
// 轮询工作站台判断是否需要下发任务
List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
.eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
.eq(Stand::getStandType, 2).orderByAsc(Stand::getStandId));
for (Stand workStation : stands) {
try {
// 分配工作
workService.distributeWorks(workStation.getStandId());
} catch (Exception e) {
log.error("分配工作时发生错误:{}", e.getMessage());
}
}
}
/**
* 执行工作
*/
public void doWork() {
String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey());
if (StringUtils.isEmpty(startWork) || !startWork.equals("1")) {
return;
}
// 轮询工作站台判断是否需要下发任务
List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
.eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
.eq(Stand::getStandType, 2));
List<String> standIds = stands.stream().map(Stand::getStandId).toList();
for (String standId : standIds) {
try {
workService.doWork(standId);
} catch (Exception e) {
log.error("执行工作时发生错误:{}", convertJsonString(e.getMessage()));
}
}
}
}

View File

@ -0,0 +1,44 @@
package com.wms.quartz.job_executor;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.service.business.IWmsJobService;
import com.wms.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import static com.wms.config.InitLocalConfig.configMap;
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class PickOutTaskSender implements Job {
/**
* WMS定时任务服务
*/
private final IWmsJobService wmsJobService;
/**
* 执行定时任务
* @param jobExecutionContext 定时任务上下文
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void execute(JobExecutionContext jobExecutionContext) {
try {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_PICK_OUT_TASK.getConfigKey());
if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
return;
}
// 发送站台拣选出库任务
wmsJobService.sendPickOutTasks();
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}

View File

@ -0,0 +1,44 @@
package com.wms.quartz.job_executor;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.service.business.IWmsJobService;
import com.wms.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import static com.wms.config.InitLocalConfig.configMap;
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class PickTaskSender implements Job {
/**
* WMS定时任务服务
*/
private final IWmsJobService wmsJobService;
/**
* 定时任务执行
* @param jobExecutionContext 执行上下文
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void execute(JobExecutionContext jobExecutionContext) {
try {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
return;
}
// 发送拣选任务
wmsJobService.sendPickTasks();
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}

View File

@ -705,10 +705,6 @@ public class WorkServiceImplements implements IWorkService {
if (!localWorkDateList.contains(currentWorkDate)) {
return;
}
if (workFlowService.exists(new LambdaQueryWrapper<>())) {
// 工作流已经生成过不做处理
return;
}
// 添加进总汇总数据
List<WorkFlow> allFlows = new ArrayList<>();
// 获取当天所有的装载机工作

View File

@ -0,0 +1,44 @@
package com.wms.service.quartz_job;
import com.wms.quartz.config.JobBean;
/**
* 定时任务服务
*/
public interface IJobService {
/**
* 创建任务
* @param jobBean 任务信息
*/
void createJob(JobBean jobBean);
/**
* 删除定时任务
* @param jobName 任务名
*/
void deleteJob(String jobName);
/**
* 修改定时任务
* @param jobBean 任务信息
*/
void modifyJob(JobBean jobBean);
/**
* 暂停定时任务
* @param jobName 任务名
*/
void pauseJob(String jobName);
/**
* 恢复定时任务
* @param jobName 任务名
*/
void resumeJob(String jobName);
/**
* 立即执行一次任务
* @param jobName 任务名
*/
void runJobOnce(String jobName);
/**
* 初始化所有的定时任务
* 只创建启用的
*/
void initAllJobs();
}

View File

@ -0,0 +1,104 @@
package com.wms.service.quartz_job.serviceImpl;
import com.wms.constants.enums.JobTimerTypeEnums;
import com.wms.quartz.JobUtils;
import com.wms.quartz.config.JobBean;
import com.wms.quartz.job_executor.*;
import com.wms.service.quartz_job.IJobService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 定时任务服务实现
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class JobServiceImpl implements IJobService {
private final Scheduler scheduler;// 调度器
/**
* 创建任务
* @param jobBean 任务信息
*/
@Override
public void createJob(JobBean jobBean) {
log.info("创建定时任务:{}。", jobBean.getJobName());
JobUtils.createJob(scheduler, jobBean);
}
/**
* 删除定时任务
* @param jobName 任务名
*/
@Override
public void deleteJob(String jobName) {
log.info("删除定时任务:{}。", jobName);
JobUtils.deleteJob(scheduler, jobName);
}
/**
* 修改定时任务
* @param jobBean 任务信息
*/
@Override
public void modifyJob(JobBean jobBean) {
log.info("修改定时任务:{}。", jobBean.getJobName());
JobUtils.modifyJob(scheduler, jobBean);
}
/**
* 暂停定时任务
* @param jobName 任务名
*/
@Override
public void pauseJob(String jobName) {
log.info("暂停定时任务:{}。", jobName);
JobUtils.pauseJob(scheduler, jobName);
}
/**
* 恢复定时任务
* @param jobName 任务名
*/
@Override
public void resumeJob(String jobName) {
log.info("恢复定时任务:{}。", jobName);
JobUtils.resumeJob(scheduler, jobName);
}
/**
* 立即执行一次任务
* @param jobName 任务名
*/
@Override
public void runJobOnce(String jobName) {
log.info("立即执行一次任务:{}。", jobName);
JobUtils.runJobOnce(scheduler, jobName);
}
/**
* 初始化所有的定时任务
* 只创建启用的
*/
@Override
public void initAllJobs() {
log.info("开始初始化定时任务。");
List<JobBean> jobBeans = new ArrayList<>();
// 这里写死五个定时器
jobBeans.add(new JobBean("CommonTaskSender", CommonTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1));
jobBeans.add(new JobBean("PickTaskSender", PickTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1));
jobBeans.add(new JobBean("PickOutTaskSender", PickOutTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1));
jobBeans.add(new JobBean("KateWorkExecutor", KateWorkExecutor.class, "0/20 * * * * ?", 20000, JobTimerTypeEnums.SIMPLE.getType(), 1));
jobBeans.add(new JobBean("DataClearExecutor", DataClearExecutor.class, "0 0 22 * * ?", null, JobTimerTypeEnums.CRON.getType(), 1));
for (JobBean jobBean : jobBeans) {
createJob(jobBean);
}
log.info("初始化定时任务结束,已启动{}个任务。", jobBeans.size());
}
}