diff --git a/ruoyi-business/pom.xml b/ruoyi-business/pom.xml index 5093bb5..7d201be 100644 --- a/ruoyi-business/pom.xml +++ b/ruoyi-business/pom.xml @@ -46,6 +46,10 @@ + + org.quartz-scheduler + quartz + diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/Apply.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/Apply.java index a244d6e..31b2cf0 100644 --- a/ruoyi-business/src/main/java/com/ruoyi/business/domain/Apply.java +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/Apply.java @@ -80,10 +80,7 @@ public class Apply extends BaseEntity @Excel(name = "是否支持应用参数") @ApiModelProperty(name="supportParam",value = "是否支持应用参数") private Integer supportParam; - /** 应用参数 */ - @Excel(name = "应用参数") - @ApiModelProperty(name="param",value = "应用参数") - private String param; + /** icon图下载地址 */ @Excel(name = "icon图下载地址") @ApiModelProperty(name="icon",value = "icon图下载地址") diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/ApplyPlan.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/ApplyPlan.java index 3309ab7..ccaf0e2 100644 --- a/ruoyi-business/src/main/java/com/ruoyi/business/domain/ApplyPlan.java +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/ApplyPlan.java @@ -112,6 +112,18 @@ public class ApplyPlan extends BaseEntity @ApiModelProperty(name="cronExpression",value = "执行表达式") private String cronExpression; + /** 上次执行时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "上次执行时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(name="lastExecTime",value = "上次执行时间") + private Date lastExecTime; + + /** 下次执行时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "下次执行时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(name="nextExecTime",value = "下次执行时间") + private Date nextExecTime; + /** 任务执行状态 */ @Excel(name = "任务执行状态") @ApiModelProperty(name="taskStatus",value = "任务执行状态") diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/IApplyPlanService.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/IApplyPlanService.java index 5ca204c..ecab306 100644 --- a/ruoyi-business/src/main/java/com/ruoyi/business/service/IApplyPlanService.java +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/IApplyPlanService.java @@ -36,6 +36,11 @@ public interface IApplyPlanService extends IService { */ boolean runAppBySetTime() throws IllegalAccessException; + /** + * 表达式执行 + */ + boolean runAppByCron() throws IllegalAccessException; + /** * 创建计划 * @param addApplyPlanBO diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/ApplyPlanServiceImpl.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/ApplyPlanServiceImpl.java index 6444c59..48d95ee 100644 --- a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/ApplyPlanServiceImpl.java +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/ApplyPlanServiceImpl.java @@ -1,5 +1,7 @@ package com.ruoyi.business.service.impl; +import java.text.ParseException; +import java.time.ZonedDateTime; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -22,7 +24,9 @@ import com.ruoyi.common.enums.RebotStatus; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; +import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.support.CronSequenceGenerator; import org.springframework.stereotype.Service; import com.ruoyi.business.mapper.ApplyPlanMapper; import com.ruoyi.business.domain.ApplyPlan; @@ -53,7 +57,7 @@ public class ApplyPlanServiceImpl extends ServiceImpl list = jsonArray.toJavaList(ApplyStartBO.RobotParam.class); @@ -92,8 +96,11 @@ public class ApplyPlanServiceImpl extends ServiceImpl listRebotVos = YinDaoHttpUtils.listRebot(listRebotBO); + if (listRebotVos.isEmpty()) { + log.error("暂无空闲机器人"); + // 刷新机器人数据 +// rebotService.syn(new Rebot()); + return false; + } + List applyPlanList = this.lambdaQuery().eq(ApplyPlan::getExcType, ExcTypeStatus.TREE.getKey()).list(); + listRebotVos.forEach(rebot -> { + applyPlanList.forEach(e -> { + // 是否满足执行条件 + boolean isExec = false; + try { + CronExpression cron = new CronExpression(e.getCronExpression()); + // 如果该计划没有执行过 + if (Objects.isNull(e.getLastExecTime())) { + // 判断当前时间是否满足表达式 + Date nextDate = cron.getNextValidTimeAfter(new Date()); + if (new Date().compareTo(nextDate) > -1) { + isExec = true; + } + } else { + // 根据表达式返回下一个执行时间 + Date nextDate = cron.getNextValidTimeAfter(e.getNextExecTime()); + if (new Date().compareTo(nextDate) > -1) { + isExec = true; + } + } + } catch (ParseException ex) { + log.error(e.getPlanName() + "的时间表达式错误!"); + throw new RuntimeException(ex); + } + + // 该计划满足执行条件 + if (isExec) { + ApplyStartBO applyStartBO = new ApplyStartBO(); + applyStartBO.setRobotUuid(e.getAppId()); + applyStartBO.setAccountName(rebot.getRobotClientName()); + applyStartBO.setManualTime(e.getManualTime()); + //high 高 middle 中 low 低 + applyStartBO.setPriority("high"); + String planParams = e.getPlanParams(); + if (StringUtils.isNotEmpty(planParams)) { + JSONArray jsonArray = JSON.parseArray(planParams); + // 直接转换成List + List list = jsonArray.toJavaList(ApplyStartBO.RobotParam.class); + applyStartBO.setPlanParamsList(list); + } + try { + JobStartVO jobStartVO = YinDaoHttpUtils.appStart(applyStartBO); + ApplyPlan applyPlan = new ApplyPlan(); + applyPlan.setId(e.getId()); + applyPlan.setUpdateBy("-1"); + applyPlan.setUpdateTime(new Date()); + applyPlan.setTaskUuid(jobStartVO.getJobUuid()); + applyPlan.setTaskStatus(PlanRunStatus.CREATED.getKey()); + // 根据表达式返回下一个执行时间 + CronExpression cron = new CronExpression(e.getCronExpression()); + Date nextDate = null; + if (Objects.isNull(e.getLastExecTime())) { + nextDate = cron.getNextValidTimeAfter(new Date()); + } else { + nextDate = cron.getNextValidTimeAfter(e.getLastExecTime()); + } + Date date = new Date(); + applyPlan.setLastExecTime(date); + applyPlan.setNextExecTime(nextDate); + this.updateById(applyPlan); + Rebot updateRebot = new Rebot(); + updateRebot.setUpdateBy("-1"); + updateRebot.setUpdateTime(new Date()); + updateRebot.setStatus(RebotStatus.RUNNING.getKey()); + rebotService.lambdaUpdate().eq(Rebot::getRobotClientName, rebot.getRobotClientName()).update(updateRebot); + applyPlanList.remove(e); + } catch (IllegalAccessException | ParseException ex) { + throw new RuntimeException(ex); + } + } + }); + }); + + return false; + } + + /** + * 判断下次执行时间是否满足条件 + * + * @param cronExpression cronExpression + * @param lastExecutionTime 上次执行时间 + * @return + * @throws ParseException + */ + private static boolean shouldExecute(String cronExpression, ZonedDateTime lastExecutionTime) throws ParseException { + CronExpression cron = new CronExpression(cronExpression); + Date now = Date.from(lastExecutionTime.toInstant()); + return cron.isSatisfiedBy(now); + } + + /** * 获取应用执行结果 * @@ -193,28 +309,35 @@ public class ApplyPlanServiceImpl extends ServiceImpl> applyPlanMap = this.lambdaQuery().eq(ApplyPlan::getExcType, ExcTypeStatus.ONE.getKey()).isNull(ApplyPlan::getTaskUuid) + .orderByAsc(ApplyPlan::getPriority).list().stream().collect(Collectors.groupingBy(ApplyPlan::getDeptId)); + + // 查询所有待执行的任务 + if (null == applyStartBO && applyPlanMap.isEmpty()) { + log.debug("没有等待执行的计划"); + return false; + } + + // 获取每个部门优先级最高的计划 + List applyPlans = new ArrayList<>(); + applyPlanMap.forEach((k, v) -> { + v.sort((Comparator.comparingInt(ApplyPlan::getPriority))); + applyPlans.add(v.get(0)); + }); + if (null == applyStartBO && applyPlans.isEmpty()) { + log.debug("没有等待执行的计划"); + return false; + } + applyPlans.sort((Comparator.comparingInt(ApplyPlan::getPriority))); + int i = 0; for (ListRebotVO listRebotVO : listRebotVos) { ApplyPlan applyPlan = null; - // 查询所有待执行的任务 - Map> applyPlanMap = this.lambdaQuery().eq(ApplyPlan::getExcType, ExcTypeStatus.ONE.getKey()).isNull(ApplyPlan::getTaskUuid) - .orderByAsc(ApplyPlan::getPriority).list().stream().collect(Collectors.groupingBy(ApplyPlan::getDeptId)); - if (null == applyStartBO && applyPlanMap.isEmpty()) { - log.debug("没有等待执行的计划"); - return false; - } - // 获取每个部门优先级最高的计划 - List applyPlans = new ArrayList<>(); - applyPlanMap.forEach((k, v) -> { - v.sort((Comparator.comparingInt(ApplyPlan::getPriority))); - applyPlans.add(v.get(0)); - }); - if (null == applyStartBO && applyPlans.isEmpty()) { - log.debug("没有等待执行的计划"); - return false; + if(applyPlans.isEmpty()){ + log.debug("没有等待执行的计划!"); + continue; } - applyPlans.sort((Comparator.comparingInt(ApplyPlan::getPriority))); - if (null == applyStartBO) { applyPlan = applyPlans.get(0); applyStartBO = new ApplyStartBO(); @@ -230,7 +353,7 @@ public class ApplyPlanServiceImpl extends ServiceImpl list = jsonArray.toJavaList(ApplyStartBO.RobotParam.class); @@ -240,6 +363,8 @@ public class ApplyPlanServiceImpl extends ServiceImpl + + + + @@ -82,6 +86,8 @@ plan.exc_type, plan.exc_time, plan.cron_expression, + plan.last_exec_time, + plan.next_exec_time, plan.task_status, plan.task_uuid, plan.manual_time, @@ -117,6 +123,8 @@ and exc_type = #{excType} and exc_time = #{excTime} and cron_expression = #{cronExpression} + and last_exec_time = #{lastExecTime} + and next_exec_time = #{nextExecTime} and task_status = #{taskStatus} and task_uuid = #{taskUuid} and manual_time = #{manualTime} @@ -129,5 +137,6 @@ ${params.dataScope} + order by plan.priority asc,plan.create_time desc \ No newline at end of file diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java index 39e9682..193a450 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java @@ -50,6 +50,16 @@ public class RyTask { log.debug("指定时间执行一次结束"); } + + /** + * 表达式执行 + */ + public void runAppByCron() throws IllegalAccessException { + log.debug("表达式执行开始"); + applyPlanService.runAppByCron(); + log.debug("表达式执行开始"); + } + /** * 获取应用执行结果 */ @@ -63,4 +73,6 @@ public class RyTask { + + }