From c81731f0a05203d01d662daf39b08b99da5ecf39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= <2270033969@qq.com> Date: Sat, 1 Mar 2025 09:57:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(quartz):=20=E6=96=B0=E5=A2=9E=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E9=85=8D=E7=BD=AE=E6=A0=A1=E9=AA=8C=E5=8A=9F=E8=83=BD?= =?UTF-8?q?#6109=20=E3=80=90=E9=9C=80=E6=B1=82=E3=80=91=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=BB=B4=E6=8A=A4=E5=A2=9E=E5=BC=BA=E5=88=A4?= =?UTF-8?q?=E6=96=AD=EF=BC=8C=E7=9B=B4=E6=8E=A5=E6=9F=A5=E8=AF=A2=20Spring?= =?UTF-8?q?Bean=20class=20=E5=88=A4=E6=96=AD=E5=85=A5=E5=8F=82=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=90=88=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pigx-visual/pigx-codegen/pom.xml | 10 -- .../quartz/controller/SysJobController.java | 108 +++++++--------- .../pigx/daemon/quartz/entity/SysJob.java | 2 + .../daemon/quartz/service/SysJobService.java | 9 ++ .../service/impl/SysJobServiceImpl.java | 116 ++++++++++++++++++ 5 files changed, 174 insertions(+), 71 deletions(-) diff --git a/pigx-visual/pigx-codegen/pom.xml b/pigx-visual/pigx-codegen/pom.xml index 722637f1b..93a646833 100755 --- a/pigx-visual/pigx-codegen/pom.xml +++ b/pigx-visual/pigx-codegen/pom.xml @@ -193,16 +193,6 @@ org.springframework.boot spring-boot-maven-plugin - - - - repackage - - - CLASSIC - - - io.fabric8 diff --git a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/controller/SysJobController.java b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/controller/SysJobController.java index 5a1ecaf32..dc20c1ecb 100644 --- a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/controller/SysJobController.java +++ b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/controller/SysJobController.java @@ -36,9 +36,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.quartz.Scheduler; -import org.quartz.SchedulerException; import org.springframework.http.HttpHeaders; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -46,8 +44,8 @@ import org.springframework.web.bind.annotation.*; import java.util.List; /** - * @author guoliang - * @date 2024-3-26 11:19:18 + * @author frwcloud + * @date 2019-01-27 10:04:42 *

* 定时任务管理 */ @@ -56,7 +54,6 @@ import java.util.List; @RequestMapping("/sys-job") @Tag(description = "sys-job", name = "定时任务") @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) -@Slf4j public class SysJobController { private final SysJobService sysJobService; @@ -72,7 +69,7 @@ public class SysJobController { * * @param page 分页对象 * @param sysJob 定时任务调度表 - * @return R + * @return */ @GetMapping("/page") @Operation(description = "分页定时业务查询") @@ -86,6 +83,19 @@ public class SysJobController { return R.ok(sysJobService.page(page, wrapper)); } + /** + * 校验任务 + * + * @param field 字段 + * @param sysJob sys 作业 + * @return {@link R } + */ + @GetMapping("/validate") + @Operation(description = "检查定时任务") + public R validate(String field, SysJob sysJob) { + return sysJobService.checkJob(field, sysJob); + } + /** * 通过id查询定时任务 * @@ -99,7 +109,7 @@ public class SysJobController { } /** - * 新增定时任务,默认新增状态为1已发布 + * 新增定时任务 * * @param sysJob 定时任务调度表 * @return R @@ -109,17 +119,8 @@ public class SysJobController { @PreAuthorize("@pms.hasPermission('job_sys_job_add')") @Operation(description = "新增定时任务") public R save(@RequestBody SysJob sysJob) { - long count = sysJobService - .count(Wrappers.query( - SysJob.builder() - .jobName(sysJob.getJobName()) - .jobGroup(sysJob.getJobGroup()) - .build() - )); - - if (count > 0) { - return R.failed("任务重复,请检查此组内是否已包含同名任务"); - } + // 初始化任务 + taskUtil.addOrUpateJob(sysJob, scheduler); sysJob.setJobStatus(PigxQuartzEnum.JOB_STATUS_RELEASE.getType()); sysJob.setCreateBy(SecurityUtils.getUser().getUsername()); return R.ok(sysJobService.save(sysJob)); @@ -139,7 +140,6 @@ public class SysJobController { sysJob.setUpdateBy(SecurityUtils.getUser().getUsername()); SysJob querySysJob = this.sysJobService.getById(sysJob.getJobId()); if (PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(querySysJob.getJobStatus())) { - //如修改暂停的需更新调度器 this.taskUtil.addOrUpateJob(sysJob, scheduler); sysJobService.updateById(sysJob); } else if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(querySysJob.getJobStatus())) { @@ -172,7 +172,7 @@ public class SysJobController { /** * 暂停全部定时任务 * - * @return R + * @return */ @SysLog("暂停全部定时任务") @PostMapping("/shutdown-jobs") @@ -185,11 +185,11 @@ public class SysJobController { if (count <= 0) { return R.ok("无正在运行定时任务"); } else { - // 更新定时任务状态条件,运行状态2更新为暂停状态3 + // 更新定时任务状态条件,运行状态2更新为暂停状态2 this.sysJobService.update( SysJob.builder().jobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()).build(), - new UpdateWrapper().lambda().eq(SysJob::getJobStatus, - PigxQuartzEnum.JOB_STATUS_RUNNING.getType())); + new UpdateWrapper().lambda() + .eq(SysJob::getJobStatus, PigxQuartzEnum.JOB_STATUS_RUNNING.getType())); return R.ok("暂停成功"); } } @@ -199,32 +199,34 @@ public class SysJobController { * * @return */ - @SysLog("启动全部暂停的定时任务") + @SysLog("启动全部定时任务") @PostMapping("/start-jobs") @PreAuthorize("@pms.hasPermission('job_sys_job_start_job')") @Operation(description = "启动全部暂停的定时任务") public R startJobs() { // 更新定时任务状态条件,暂停状态3更新为运行状态2 this.sysJobService.update(SysJob.builder().jobStatus(PigxQuartzEnum.JOB_STATUS_RUNNING.getType()).build(), - new UpdateWrapper().lambda().eq(SysJob::getJobStatus, - PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType())); + new UpdateWrapper().lambda() + .eq(SysJob::getJobStatus, PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType())); taskUtil.startJobs(scheduler); return R.ok(); } /** * 刷新全部定时任务 - * 暂停和运行的添加到调度器其他状态从调度器移除 * - * @return R + * @return */ @SysLog("刷新全部定时任务") @PostMapping("/refresh-jobs") - @PreAuthorize("@pms.hasPermission('job_sys_job_refresh_job')") + @PreAuthorize("job_sys_job_refresh_job") @Operation(description = "刷新全部定时任务") public R refreshJobs() { - sysJobService.list().forEach(sysjob -> { - if (PigxQuartzEnum.JOB_STATUS_RUNNING.getType().equals(sysjob.getJobStatus()) + sysJobService.list().forEach((sysjob) -> { + if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(sysjob.getJobStatus()) + || PigxQuartzEnum.JOB_STATUS_DEL.getType().equals(sysjob.getJobStatus())) { + taskUtil.removeJob(sysjob, scheduler); + } else if (PigxQuartzEnum.JOB_STATUS_RUNNING.getType().equals(sysjob.getJobStatus()) || PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(sysjob.getJobStatus())) { taskUtil.addOrUpateJob(sysjob, scheduler); } else { @@ -237,56 +239,38 @@ public class SysJobController { /** * 启动定时任务 * - * @param jobId 任务id - * @return R + * @param jobId + * @return */ @SysLog("启动定时任务") @PostMapping("/start-job/{id}") @PreAuthorize("@pms.hasPermission('job_sys_job_start_job')") @Operation(description = "启动定时任务") - public R startJob(@PathVariable("id") Long jobId) throws SchedulerException { + public R startJob(@PathVariable("id") Long jobId) { SysJob querySysJob = this.sysJobService.getById(jobId); - if (querySysJob == null) { - return R.failed("无此定时任务,请确认"); - } - - //如果定时任务不存在,强制状态为1已发布 - if (!scheduler.checkExists(TaskUtil.getJobKey(querySysJob))) { - querySysJob.setJobStatus(PigxQuartzEnum.JOB_STATUS_RELEASE.getType()); - log.warn("定时任务不在quartz中,任务id:{},强制状态为已发布并加入调度器", jobId); - } - - if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(querySysJob.getJobStatus())) { + if (querySysJob != null && PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType().equals(querySysJob.getJobStatus())) { taskUtil.addOrUpateJob(querySysJob, scheduler); } else { taskUtil.resumeJob(querySysJob, scheduler); } - // 更新定时任务状态为运行状态2 - this.sysJobService.updateById( - SysJob.builder().jobId(jobId).jobStatus(PigxQuartzEnum.JOB_STATUS_RUNNING.getType()).build()); + // 更新定时任务状态条件,暂停状态3更新为运行状态2 + this.sysJobService + .updateById(SysJob.builder().jobId(jobId).jobStatus(PigxQuartzEnum.JOB_STATUS_RUNNING.getType()).build()); return R.ok(); } /** * 启动定时任务 * - * @param jobId 任务id - * @return R + * @param jobId + * @return */ @SysLog("立刻执行定时任务") @PostMapping("/run-job/{id}") @PreAuthorize("@pms.hasPermission('job_sys_job_run_job')") @Operation(description = "立刻执行定时任务") - public R runJob(@PathVariable("id") Long jobId) throws SchedulerException { + public R runJob(@PathVariable("id") Long jobId) { SysJob querySysJob = this.sysJobService.getById(jobId); - - //执行定时任务前判定任务是否在quartz中 - if (!scheduler.checkExists(TaskUtil.getJobKey(querySysJob))) { - querySysJob.setJobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()); - log.warn("立刻执行定时任务-定时任务不在quartz中,任务id:{},强制状态为暂停并加入调度器", jobId); - taskUtil.addOrUpateJob(querySysJob, scheduler); - } - return TaskUtil.runOnce(scheduler, querySysJob) ? R.ok() : R.failed(); } @@ -302,8 +286,10 @@ public class SysJobController { public R shutdownJob(@PathVariable("id") Long id) { SysJob querySysJob = this.sysJobService.getById(id); // 更新定时任务状态条件,运行状态2更新为暂停状态3 - this.sysJobService.updateById(SysJob.builder().jobId(querySysJob.getJobId()) - .jobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()).build()); + this.sysJobService.updateById(SysJob.builder() + .jobId(querySysJob.getJobId()) + .jobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()) + .build()); taskUtil.pauseJob(querySysJob, scheduler); return R.ok(); } diff --git a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/entity/SysJob.java b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/entity/SysJob.java index ffbb979a7..ce0a6fc3b 100644 --- a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/entity/SysJob.java +++ b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/entity/SysJob.java @@ -25,6 +25,7 @@ import com.baomidou.mybatisplus.extension.activerecord.Model; import com.pig4cloud.pigx.common.core.util.TenantTable; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import lombok.experimental.FieldNameConstants; import java.time.LocalDateTime; @@ -38,6 +39,7 @@ import java.time.LocalDateTime; @TenantTable @NoArgsConstructor @AllArgsConstructor +@FieldNameConstants @Schema(description = "定时任务") @EqualsAndHashCode(callSuper = true) public class SysJob extends Model { diff --git a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/SysJobService.java b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/SysJobService.java index 832413598..37c8e807e 100644 --- a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/SysJobService.java +++ b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/SysJobService.java @@ -18,6 +18,7 @@ package com.pig4cloud.pigx.daemon.quartz.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.daemon.quartz.entity.SysJob; /** @@ -28,4 +29,12 @@ import com.pig4cloud.pigx.daemon.quartz.entity.SysJob; */ public interface SysJobService extends IService { + /** + * 检查任务配置 + * + * @param field 字段 + * @param sysJob sys 作业 + * @return {@link R } + */ + R checkJob(String field, SysJob sysJob); } diff --git a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/impl/SysJobServiceImpl.java b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/impl/SysJobServiceImpl.java index 5d6afa798..62e57b45f 100644 --- a/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/impl/SysJobServiceImpl.java +++ b/pigx-visual/pigx-daemon-quartz/src/main/java/com/pig4cloud/pigx/daemon/quartz/service/impl/SysJobServiceImpl.java @@ -17,14 +17,24 @@ package com.pig4cloud.pigx.daemon.quartz.service.impl; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.daemon.quartz.constants.JobTypeQuartzEnum; import com.pig4cloud.pigx.daemon.quartz.entity.SysJob; import com.pig4cloud.pigx.daemon.quartz.mapper.SysJobMapper; import com.pig4cloud.pigx.daemon.quartz.service.SysJobService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.Nullable; import org.springframework.stereotype.Service; +import java.lang.reflect.Method; +import java.util.Objects; + /** * 定时任务调度表 * @@ -36,4 +46,110 @@ import org.springframework.stereotype.Service; @AllArgsConstructor public class SysJobServiceImpl extends ServiceImpl implements SysJobService { + /** + * 检查任务配置 + * + * @param field + * @param sysJob sys 作业 + * @return {@link R } + */ + @Override + public R checkJob(String field, SysJob sysJob) { + // 如果是 spring bean 类型任务 + if (JobTypeQuartzEnum.SPRING_BEAN.getType().equals(sysJob.getJobType())) { + + R ok = checkSpringBeanType(field, sysJob); + if (ok != null) return ok; + } + + if (JobTypeQuartzEnum.JAVA.getType().equals(sysJob.getJobType())) { + + R ok = checkClassType(field, sysJob); + if (ok != null) return ok; + } + return R.ok(); + } + + /** + * 检查类类型 + * + * @param field 字段 + * @param sysJob sys 作业 + * @return {@link R }<{@link ? }> + */ + @Nullable + private static R checkClassType(String field, SysJob sysJob) { + if (StrUtil.isEmpty(sysJob.getClassName())) { + return R.ok("Class方式,类名称必须填写"); + } + + if (SysJob.Fields.className.equals(field)) { + try { + Class.forName(sysJob.getClassName()); + return R.ok(); + } catch (ClassNotFoundException e) { + return R.ok("当前服务中,不包含此类路径"); + } + } + + Class objectClass = ClassUtil.loadClass(sysJob.getClassName()); + if (SysJob.Fields.methodName.equals(field)) { + Method method = ReflectUtil.getMethodByName(objectClass, sysJob.getMethodName()); + if (Objects.isNull(method)) { + return R.ok("当前Class 未找到此方法"); + } + } + + Method method = ReflectUtil.getMethodByName(objectClass, sysJob.getMethodName()); + if (StrUtil.isNotBlank(sysJob.getMethodParamsValue())) { + if (method.getParameterCount() == 0) { + return R.ok("当前方法不需要参数,请清空参数值"); + } + } else if (method.getParameterCount() != 0) { + return R.ok("当前方法需要参数,请填写 【参数值】字段"); + } + return null; + } + + /** + * 检查 Spring Bean 类型 + * + * @param field 字段 + * @param sysJob sys 作业 + * @return {@link R }<{@link ? }> + */ + @Nullable + private static R checkSpringBeanType(String field, SysJob sysJob) { + if (StrUtil.isEmpty(sysJob.getClassName())) { + return R.ok("spring bean方式,Bean名称必须填写"); + } + + + if (SysJob.Fields.className.equals(field)) { + if (SpringUtil.getApplicationContext().containsBean(sysJob.getClassName())) { + return R.ok(); + } + return R.ok("当前服务未找到此Bean"); + } + + + if (SysJob.Fields.methodName.equals(field)) { + Method method = ReflectUtil.getMethodByName(SpringUtil.getBean(sysJob.getClassName()).getClass(), sysJob.getMethodName()); + if (Objects.isNull(method)) { + return R.ok("当前Bean未找到此方法"); + } + return R.ok(); + } + + + Method method = ReflectUtil.getMethodByName(SpringUtil.getBean(sysJob.getClassName()).getClass(), sysJob.getMethodName()); + if (StrUtil.isNotBlank(sysJob.getMethodParamsValue())) { + if (method.getParameterCount() == 0) { + return R.ok("当前方法不需要参数,请清空参数值"); + } + } else if (method.getParameterCount() != 0) { + return R.ok("当前方法需要参数,请填写 【参数值】字段"); + } + return null; + } }