From e7613a0fe931b6065cca50e4013e3c655970cdd0 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期二, 02 四月 2024 10:33:06 +0800
Subject: [PATCH] 定时任务集成
---
ycl-server/src/main/java/com/ycl/utils/quartz/CronUtils.java | 64 +
ycl-server/src/main/java/com/ycl/system/controller/SysJobController.java | 178 +++++
ycl-server/src/main/java/com/ycl/system/service/ISysJobService.java | 103 ++
ycl-server/src/main/java/com/ycl/utils/quartz/AbstractQuartzJob.java | 108 +++
ycl-pojo/src/main/java/com/ycl/system/domain/SysJob.java | 171 ++++
ycl-server/pom.xml | 3
ycl-server/src/main/java/com/ycl/system/service/ISysJobLogService.java | 57 +
ycl-server/src/main/java/com/ycl/system/service/impl/SysJobLogServiceImpl.java | 89 ++
ycl-server/src/main/java/com/ycl/system/mapper/SysJobLogMapper.java | 65 +
ycl-server/src/main/java/com/ycl/utils/quartz/JobInvokeUtil.java | 183 +++++
ycl-pojo/src/main/java/com/ycl/system/domain/SysJobLog.java | 156 ++++
ycl-server/src/main/java/com/ycl/utils/quartz/QuartzJobExecution.java | 19
ycl-server/src/main/java/com/ycl/system/mapper/SysJobMapper.java | 68 +
ycl-server/src/main/java/com/ycl/utils/quartz/ScheduleUtils.java | 131 +++
ycl-server/src/main/resources/mapper/system/SysJobMapper.xml | 111 +++
ycl-common/pom.xml | 13
ycl-server/src/main/resources/mapper/system/SysJobLogMapper.xml | 94 ++
ycl-server/src/main/java/com/ycl/task/RyTask.java | 28
ycl-server/src/main/java/com/ycl/utils/quartz/QuartzDisallowConcurrentExecution.java | 21
ycl-common/src/main/java/utils/CronUtils.java | 64 +
ycl-server/src/main/java/com/ycl/system/service/impl/SysJobServiceImpl.java | 261 +++++++
ycl-server/src/main/java/com/ycl/system/controller/SysJobLogController.java | 87 ++
22 files changed, 2,073 insertions(+), 1 deletions(-)
diff --git a/ycl-common/pom.xml b/ycl-common/pom.xml
index d5b3290..4f8f328 100644
--- a/ycl-common/pom.xml
+++ b/ycl-common/pom.xml
@@ -16,6 +16,19 @@
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
+
+ <!-- 瀹氭椂浠诲姟 -->
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
<!-- 鑷畾涔夐獙璇佹敞瑙� -->
<dependency>
<groupId>org.springframework.boot</groupId>
diff --git a/ycl-common/src/main/java/utils/CronUtils.java b/ycl-common/src/main/java/utils/CronUtils.java
new file mode 100644
index 0000000..0077c82
--- /dev/null
+++ b/ycl-common/src/main/java/utils/CronUtils.java
@@ -0,0 +1,64 @@
+package utils;
+
+import org.quartz.CronExpression;
+
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * cron琛ㄨ揪寮忓伐鍏风被
+ *
+ * @author ruoyi
+ *
+ */
+public class CronUtils
+{
+ /**
+ * 杩斿洖涓�涓竷灏斿�间唬琛ㄤ竴涓粰瀹氱殑Cron琛ㄨ揪寮忕殑鏈夋晥鎬�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return boolean 琛ㄨ揪寮忔槸鍚︽湁鏁�
+ */
+ public static boolean isValid(String cronExpression)
+ {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 杩斿洖涓�涓瓧绗︿覆鍊�,琛ㄧず璇ユ秷鎭棤鏁圕ron琛ㄨ揪寮忕粰鍑烘湁鏁堟��
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return String 鏃犳晥鏃惰繑鍥炶〃杈惧紡閿欒鎻忚堪,濡傛灉鏈夋晥杩斿洖null
+ */
+ public static String getInvalidMessage(String cronExpression)
+ {
+ try
+ {
+ new CronExpression(cronExpression);
+ return null;
+ }
+ catch (ParseException pe)
+ {
+ return pe.getMessage();
+ }
+ }
+
+ /**
+ * 杩斿洖涓嬩竴涓墽琛屾椂闂存牴鎹粰瀹氱殑Cron琛ㄨ揪寮�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return Date 涓嬫Cron琛ㄨ揪寮忔墽琛屾椂闂�
+ */
+ public static Date getNextExecution(String cronExpression)
+ {
+ try
+ {
+ CronExpression cron = new CronExpression(cronExpression);
+ return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+}
diff --git a/ycl-pojo/src/main/java/com/ycl/system/domain/SysJob.java b/ycl-pojo/src/main/java/com/ycl/system/domain/SysJob.java
new file mode 100644
index 0000000..8d5d476
--- /dev/null
+++ b/ycl-pojo/src/main/java/com/ycl/system/domain/SysJob.java
@@ -0,0 +1,171 @@
+package com.ycl.system.domain;
+
+import annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import constant.ScheduleConstants;
+import jakarta.validation.constraints.NotBlank;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import pojo.BaseEntity;
+import utils.CronUtils;
+import utils.StringUtils;
+
+import javax.validation.constraints.Size;
+import java.util.Date;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害琛� sys_job
+ *
+ * @author ruoyi
+ */
+public class SysJob extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 浠诲姟ID */
+ @Excel(name = "浠诲姟搴忓彿", cellType = Excel.ColumnType.NUMERIC)
+ private Long jobId;
+
+ /** 浠诲姟鍚嶇О */
+ @Excel(name = "浠诲姟鍚嶇О")
+ private String jobName;
+
+ /** 浠诲姟缁勫悕 */
+ @Excel(name = "浠诲姟缁勫悕")
+ private String jobGroup;
+
+ /** 璋冪敤鐩爣瀛楃涓� */
+ @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+ private String invokeTarget;
+
+ /** cron鎵ц琛ㄨ揪寮� */
+ @Excel(name = "鎵ц琛ㄨ揪寮� ")
+ private String cronExpression;
+
+ /** cron璁″垝绛栫暐 */
+ @Excel(name = "璁″垝绛栫暐 ", readConverterExp = "0=榛樿,1=绔嬪嵆瑙﹀彂鎵ц,2=瑙﹀彂涓�娆℃墽琛�,3=涓嶈Е鍙戠珛鍗虫墽琛�")
+ private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
+
+ /** 鏄惁骞跺彂鎵ц锛�0鍏佽 1绂佹锛� */
+ @Excel(name = "骞跺彂鎵ц", readConverterExp = "0=鍏佽,1=绂佹")
+ private String concurrent;
+
+ /** 浠诲姟鐘舵�侊紙0姝e父 1鏆傚仠锛� */
+ @Excel(name = "浠诲姟鐘舵��", readConverterExp = "0=姝e父,1=鏆傚仠")
+ private String status;
+
+ public Long getJobId()
+ {
+ return jobId;
+ }
+
+ public void setJobId(Long jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ @NotBlank(message = "浠诲姟鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 64, message = "浠诲姟鍚嶇О涓嶈兘瓒呰繃64涓瓧绗�")
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ @NotBlank(message = "璋冪敤鐩爣瀛楃涓蹭笉鑳戒负绌�")
+ @Size(min = 0, max = 500, message = "璋冪敤鐩爣瀛楃涓查暱搴︿笉鑳借秴杩�500涓瓧绗�")
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ @NotBlank(message = "Cron鎵ц琛ㄨ揪寮忎笉鑳戒负绌�")
+ @Size(min = 0, max = 255, message = "Cron鎵ц琛ㄨ揪寮忎笉鑳借秴杩�255涓瓧绗�")
+ public String getCronExpression()
+ {
+ return cronExpression;
+ }
+
+ public void setCronExpression(String cronExpression)
+ {
+ this.cronExpression = cronExpression;
+ }
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ public Date getNextValidTime()
+ {
+ if (StringUtils.isNotEmpty(cronExpression))
+ {
+ return CronUtils.getNextExecution(cronExpression);
+ }
+ return null;
+ }
+
+ public String getMisfirePolicy()
+ {
+ return misfirePolicy;
+ }
+
+ public void setMisfirePolicy(String misfirePolicy)
+ {
+ this.misfirePolicy = misfirePolicy;
+ }
+
+ public String getConcurrent()
+ {
+ return concurrent;
+ }
+
+ public void setConcurrent(String concurrent)
+ {
+ this.concurrent = concurrent;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobId", getJobId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("cronExpression", getCronExpression())
+ .append("nextValidTime", getNextValidTime())
+ .append("misfirePolicy", getMisfirePolicy())
+ .append("concurrent", getConcurrent())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ycl-pojo/src/main/java/com/ycl/system/domain/SysJobLog.java b/ycl-pojo/src/main/java/com/ycl/system/domain/SysJobLog.java
new file mode 100644
index 0000000..ec97001
--- /dev/null
+++ b/ycl-pojo/src/main/java/com/ycl/system/domain/SysJobLog.java
@@ -0,0 +1,156 @@
+package com.ycl.system.domain;
+
+import annotation.Excel;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import pojo.BaseEntity;
+
+import java.util.Date;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織琛� sys_job_log
+ *
+ * @author ruoyi
+ */
+public class SysJobLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** ID */
+ @Excel(name = "鏃ュ織搴忓彿")
+ private Long jobLogId;
+
+ /** 浠诲姟鍚嶇О */
+ @Excel(name = "浠诲姟鍚嶇О")
+ private String jobName;
+
+ /** 浠诲姟缁勫悕 */
+ @Excel(name = "浠诲姟缁勫悕")
+ private String jobGroup;
+
+ /** 璋冪敤鐩爣瀛楃涓� */
+ @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+ private String invokeTarget;
+
+ /** 鏃ュ織淇℃伅 */
+ @Excel(name = "鏃ュ織淇℃伅")
+ private String jobMessage;
+
+ /** 鎵ц鐘舵�侊紙0姝e父 1澶辫触锛� */
+ @Excel(name = "鎵ц鐘舵��", readConverterExp = "0=姝e父,1=澶辫触")
+ private String status;
+
+ /** 寮傚父淇℃伅 */
+ @Excel(name = "寮傚父淇℃伅")
+ private String exceptionInfo;
+
+ /** 寮�濮嬫椂闂� */
+ private Date startTime;
+
+ /** 鍋滄鏃堕棿 */
+ private Date stopTime;
+
+ public Long getJobLogId()
+ {
+ return jobLogId;
+ }
+
+ public void setJobLogId(Long jobLogId)
+ {
+ this.jobLogId = jobLogId;
+ }
+
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ public String getJobMessage()
+ {
+ return jobMessage;
+ }
+
+ public void setJobMessage(String jobMessage)
+ {
+ this.jobMessage = jobMessage;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getExceptionInfo()
+ {
+ return exceptionInfo;
+ }
+
+ public void setExceptionInfo(String exceptionInfo)
+ {
+ this.exceptionInfo = exceptionInfo;
+ }
+
+ public Date getStartTime()
+ {
+ return startTime;
+ }
+
+ public void setStartTime(Date startTime)
+ {
+ this.startTime = startTime;
+ }
+
+ public Date getStopTime()
+ {
+ return stopTime;
+ }
+
+ public void setStopTime(Date stopTime)
+ {
+ this.stopTime = stopTime;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobLogId", getJobLogId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("jobMessage", getJobMessage())
+ .append("status", getStatus())
+ .append("exceptionInfo", getExceptionInfo())
+ .append("startTime", getStartTime())
+ .append("stopTime", getStopTime())
+ .toString();
+ }
+}
diff --git a/ycl-server/pom.xml b/ycl-server/pom.xml
index b30767c..931bb3f 100644
--- a/ycl-server/pom.xml
+++ b/ycl-server/pom.xml
@@ -44,6 +44,7 @@
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
+
<!-- 楠岃瘉鐮� -->
<dependency>
<groupId>pro.fessional</groupId>
@@ -119,4 +120,4 @@
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/ycl-server/src/main/java/com/ycl/system/controller/SysJobController.java b/ycl-server/src/main/java/com/ycl/system/controller/SysJobController.java
new file mode 100644
index 0000000..e59a20d
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/controller/SysJobController.java
@@ -0,0 +1,178 @@
+package com.ycl.system.controller;
+
+import annotation.Log;
+import com.ycl.exception.job.TaskException;
+import com.ycl.system.AjaxResult;
+import com.ycl.system.domain.SysJob;
+import com.ycl.system.page.TableDataInfo;
+import com.ycl.system.service.ISysJobService;
+import com.ycl.utils.StringUtils;
+import com.ycl.utils.poi.ExcelUtil;
+import com.ycl.utils.quartz.CronUtils;
+import com.ycl.utils.quartz.ScheduleUtils;
+import constant.Constants;
+import enumeration.BusinessType;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 璋冨害浠诲姟淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/job")
+public class SysJobController extends BaseController
+{
+ @Autowired
+ private ISysJobService jobService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJob sysJob)
+ {
+ startPage();
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJob sysJob)
+ {
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
+ util.exportExcel(response, list, "瀹氭椂浠诲姟");
+ }
+
+ /**
+ * 鑾峰彇瀹氭椂浠诲姟璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobId}")
+ public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
+ {
+ return success(jobService.selectJobById(jobId));
+ }
+
+ /**
+ * 鏂板瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:add')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setCreateBy(getUsername());
+ return toAjax(jobService.insertJob(job));
+ }
+
+ /**
+ * 淇敼瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setUpdateBy(getUsername());
+ return toAjax(jobService.updateJob(job));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
+ {
+ SysJob newJob = jobService.selectJobById(job.getJobId());
+ newJob.setStatus(job.getStatus());
+ return toAjax(jobService.changeStatus(newJob));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/run")
+ public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
+ {
+ boolean result = jobService.run(job);
+ return result ? success() : error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紒");
+ }
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobIds}")
+ public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
+ {
+ jobService.deleteJobByIds(jobIds);
+ return success();
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/controller/SysJobLogController.java b/ycl-server/src/main/java/com/ycl/system/controller/SysJobLogController.java
new file mode 100644
index 0000000..75b5398
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/controller/SysJobLogController.java
@@ -0,0 +1,87 @@
+package com.ycl.system.controller;
+
+import annotation.Log;
+import com.ycl.system.AjaxResult;
+import com.ycl.system.domain.SysJobLog;
+import com.ycl.system.page.TableDataInfo;
+import com.ycl.system.service.ISysJobLogService;
+import enumeration.BusinessType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import utils.poi.ExcelUtil;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 璋冨害鏃ュ織鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/jobLog")
+public class SysJobLogController extends BaseController
+{
+ @Autowired
+ private ISysJobLogService jobLogService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJobLog sysJobLog)
+ {
+ startPage();
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "浠诲姟璋冨害鏃ュ織", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJobLog sysJobLog)
+ {
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
+ util.exportExcel(response, list, "璋冨害鏃ュ織");
+ }
+
+ /**
+ * 鏍规嵁璋冨害缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobLogId}")
+ public AjaxResult getInfo(@PathVariable Long jobLogId)
+ {
+ return success(jobLogService.selectJobLogById(jobLogId));
+ }
+
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟璋冨害鏃ュ織", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobLogIds}")
+ public AjaxResult remove(@PathVariable Long[] jobLogIds)
+ {
+ return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
+ }
+
+ /**
+ * 娓呯┖瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "璋冨害鏃ュ織", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ jobLogService.cleanJobLog();
+ return success();
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/mapper/SysJobLogMapper.java b/ycl-server/src/main/java/com/ycl/system/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..cce1c57
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/mapper/SysJobLogMapper.java
@@ -0,0 +1,65 @@
+package com.ycl.system.mapper;
+
+import com.ycl.system.domain.SysJobLog;
+
+import java.util.List;
+
+/**
+ * 璋冨害浠诲姟鏃ュ織淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysJobLogMapper
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 鏌ヨ鎵�鏈夎皟搴︿换鍔℃棩蹇�
+ *
+ * @return 璋冨害浠诲姟鏃ュ織鍒楄〃
+ */
+ public List<SysJobLog> selectJobLogAll();
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJobLog(SysJobLog jobLog);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ public void cleanJobLog();
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/mapper/SysJobMapper.java b/ycl-server/src/main/java/com/ycl/system/mapper/SysJobMapper.java
new file mode 100644
index 0000000..96be5db
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/mapper/SysJobMapper.java
@@ -0,0 +1,68 @@
+package com.ycl.system.mapper;
+
+import com.ycl.system.domain.SysJob;
+
+import java.util.List;
+
+/**
+ * 璋冨害浠诲姟淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysJobMapper
+{
+ /**
+ * 鏌ヨ璋冨害浠诲姟鏃ュ織闆嗗悎
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 鎿嶄綔鏃ュ織闆嗗悎
+ */
+ public List<SysJob> selectJobList(SysJob job);
+
+ /**
+ * 鏌ヨ鎵�鏈夎皟搴︿换鍔�
+ *
+ * @return 璋冨害浠诲姟鍒楄〃
+ */
+ public List<SysJob> selectJobAll();
+
+ /**
+ * 閫氳繃璋冨害ID鏌ヨ璋冨害浠诲姟淇℃伅
+ *
+ * @param jobId 璋冨害ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 閫氳繃璋冨害ID鍒犻櫎璋冨害浠诲姟淇℃伅
+ *
+ * @param jobId 璋冨害ID
+ * @return 缁撴灉
+ */
+ public int deleteJobById(Long jobId);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害浠诲姟淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteJobByIds(Long[] ids);
+
+ /**
+ * 淇敼璋冨害浠诲姟淇℃伅
+ *
+ * @param job 璋冨害浠诲姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateJob(SysJob job);
+
+ /**
+ * 鏂板璋冨害浠诲姟淇℃伅
+ *
+ * @param job 璋冨害浠诲姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJob(SysJob job);
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/service/ISysJobLogService.java b/ycl-server/src/main/java/com/ycl/system/service/ISysJobLogService.java
new file mode 100644
index 0000000..9925c41
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/service/ISysJobLogService.java
@@ -0,0 +1,57 @@
+package com.ycl.system.service;
+
+import com.ycl.system.domain.SysJobLog;
+
+import java.util.List;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysJobLogService
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ */
+ public void addJobLog(SysJobLog jobLog);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ public void cleanJobLog();
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/service/ISysJobService.java b/ycl-server/src/main/java/com/ycl/system/service/ISysJobService.java
new file mode 100644
index 0000000..6dbf13a
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/service/ISysJobService.java
@@ -0,0 +1,103 @@
+package com.ycl.system.service;
+
+import com.ycl.exception.job.TaskException;
+import com.ycl.system.domain.SysJob;
+import org.quartz.SchedulerException;
+
+import java.util.List;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysJobService
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 璋冨害浠诲姟闆嗗悎
+ */
+ public List<SysJob> selectJobList(SysJob job);
+
+ /**
+ * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobId 璋冨害浠诲姟ID
+ * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 鏆傚仠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int pauseJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鎭㈠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int resumeJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int deleteJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害淇℃伅
+ *
+ * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+ * @return 缁撴灉
+ */
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException;
+
+ /**
+ * 浠诲姟璋冨害鐘舵�佷慨鏀�
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int changeStatus(SysJob job) throws SchedulerException;
+
+ /**
+ * 绔嬪嵆杩愯浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean run(SysJob job) throws SchedulerException;
+
+ /**
+ * 鏂板浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 鏇存柊浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+ *
+ * @param cronExpression 琛ㄨ揪寮�
+ * @return 缁撴灉
+ */
+ public boolean checkCronExpressionIsValid(String cronExpression);
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobLogServiceImpl.java b/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..d61c53a
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobLogServiceImpl.java
@@ -0,0 +1,89 @@
+package com.ycl.system.service.impl;
+
+import com.ycl.system.domain.SysJobLog;
+import com.ycl.system.mapper.SysJobLogMapper;
+import com.ycl.system.service.ISysJobLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+@Service
+@RequiredArgsConstructor
+public class SysJobLogServiceImpl implements ISysJobLogService
+{
+ private final SysJobLogMapper jobLogMapper;
+
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ @Override
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog)
+ {
+ return jobLogMapper.selectJobLogList(jobLog);
+ }
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ @Override
+ public SysJobLog selectJobLogById(Long jobLogId)
+ {
+ return jobLogMapper.selectJobLogById(jobLogId);
+ }
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ */
+ @Override
+ public void addJobLog(SysJobLog jobLog)
+ {
+ jobLogMapper.insertJobLog(jobLog);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteJobLogByIds(Long[] logIds)
+ {
+ return jobLogMapper.deleteJobLogByIds(logIds);
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ */
+ @Override
+ public int deleteJobLogById(Long jobId)
+ {
+ return jobLogMapper.deleteJobLogById(jobId);
+ }
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ @Override
+ public void cleanJobLog()
+ {
+ jobLogMapper.cleanJobLog();
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobServiceImpl.java b/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobServiceImpl.java
new file mode 100644
index 0000000..07d28a5
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/system/service/impl/SysJobServiceImpl.java
@@ -0,0 +1,261 @@
+package com.ycl.system.service.impl;
+
+import com.ycl.exception.job.TaskException;
+import com.ycl.system.domain.SysJob;
+import com.ycl.system.mapper.SysJobMapper;
+import com.ycl.system.service.ISysJobService;
+import com.ycl.utils.quartz.CronUtils;
+import com.ycl.utils.quartz.ScheduleUtils;
+import constant.ScheduleConstants;
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+@Service
+@RequiredArgsConstructor
+public class SysJobServiceImpl implements ISysJobService
+{
+ private final Scheduler scheduler;
+ private final SysJobMapper jobMapper;
+
+ /**
+ * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧畾鏃跺櫒 涓昏鏄槻姝㈡墜鍔ㄤ慨鏀规暟鎹簱瀵艰嚧鏈悓姝ュ埌瀹氭椂浠诲姟澶勭悊锛堟敞锛氫笉鑳芥墜鍔ㄤ慨鏀规暟鎹簱ID鍜屼换鍔$粍鍚嶏紝鍚﹀垯浼氬鑷磋剰鏁版嵁锛�
+ */
+ @PostConstruct
+ public void init() throws SchedulerException, TaskException
+ {
+ scheduler.clear();
+ List<SysJob> jobList = jobMapper.selectJobAll();
+ for (SysJob job : jobList)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ }
+
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟鍒楄〃
+ *
+ * @param job 璋冨害淇℃伅
+ * @return
+ */
+ @Override
+ public List<SysJob> selectJobList(SysJob job)
+ {
+ return jobMapper.selectJobList(job);
+ }
+
+ /**
+ * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobId 璋冨害浠诲姟ID
+ * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+ */
+ @Override
+ public SysJob selectJobById(Long jobId)
+ {
+ return jobMapper.selectJobById(jobId);
+ }
+
+ /**
+ * 鏆傚仠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int pauseJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鎭㈠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int resumeJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deleteJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ int rows = jobMapper.deleteJobById(jobId);
+ if (rows > 0)
+ {
+ scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害淇℃伅
+ *
+ * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException
+ {
+ for (Long jobId : jobIds)
+ {
+ SysJob job = jobMapper.selectJobById(jobId);
+ deleteJob(job);
+ }
+ }
+
+ /**
+ * 浠诲姟璋冨害鐘舵�佷慨鏀�
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int changeStatus(SysJob job) throws SchedulerException
+ {
+ int rows = 0;
+ String status = job.getStatus();
+ if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
+ {
+ rows = resumeJob(job);
+ }
+ else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
+ {
+ rows = pauseJob(job);
+ }
+ return rows;
+ }
+
+ /**
+ * 绔嬪嵆杩愯浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean run(SysJob job) throws SchedulerException
+ {
+ boolean result = false;
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ SysJob properties = selectJobById(job.getJobId());
+ // 鍙傛暟
+ JobDataMap dataMap = new JobDataMap();
+ dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ result = true;
+ scheduler.triggerJob(jobKey, dataMap);
+ }
+ return result;
+ }
+
+ /**
+ * 鏂板浠诲姟
+ *
+ * @param job 璋冨害淇℃伅 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int insertJob(SysJob job) throws SchedulerException, TaskException
+ {
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.insertJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 鏇存柊浠诲姟鐨勬椂闂磋〃杈惧紡
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int updateJob(SysJob job) throws SchedulerException, TaskException
+ {
+ SysJob properties = selectJobById(job.getJobId());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ updateSchedulerJob(job, properties.getJobGroup());
+ }
+ return rows;
+ }
+
+ /**
+ * 鏇存柊浠诲姟
+ *
+ * @param job 浠诲姟瀵硅薄
+ * @param jobGroup 浠诲姟缁勫悕
+ */
+ public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException
+ {
+ Long jobId = job.getJobId();
+ // 鍒ゆ柇鏄惁瀛樺湪
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+ scheduler.deleteJob(jobKey);
+ }
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+
+ /**
+ * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+ *
+ * @param cronExpression 琛ㄨ揪寮�
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkCronExpressionIsValid(String cronExpression)
+ {
+ return CronUtils.isValid(cronExpression);
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/task/RyTask.java b/ycl-server/src/main/java/com/ycl/task/RyTask.java
new file mode 100644
index 0000000..7a4f295
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.ycl.task;
+
+import com.ycl.utils.StringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害娴嬭瘯
+ *
+ * @author ruoyi
+ */
+@Component("ryTask")
+public class RyTask
+{
+ public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
+ {
+ System.out.println(StringUtils.format("鎵ц澶氬弬鏂规硶锛� 瀛楃涓茬被鍨媨}锛屽竷灏旂被鍨媨}锛岄暱鏁村瀷{}锛屾诞鐐瑰瀷{}锛屾暣褰}", s, b, l, d, i));
+ }
+
+ public void ryParams(String params)
+ {
+ System.out.println("鎵ц鏈夊弬鏂规硶锛�" + params);
+ }
+
+ public void ryNoParams()
+ {
+ System.out.println("鎵ц鏃犲弬鏂规硶");
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/AbstractQuartzJob.java b/ycl-server/src/main/java/com/ycl/utils/quartz/AbstractQuartzJob.java
new file mode 100644
index 0000000..b46e906
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/AbstractQuartzJob.java
@@ -0,0 +1,108 @@
+package com.ycl.utils.quartz;
+
+import com.ycl.system.domain.SysJob;
+import com.ycl.system.domain.SysJobLog;
+import com.ycl.system.service.ISysJobLogService;
+import com.ycl.utils.ExceptionUtil;
+import com.ycl.utils.StringUtils;
+import com.ycl.utils.bean.BeanUtils;
+import com.ycl.utils.spring.SpringUtils;
+import constant.Constants;
+import constant.ScheduleConstants;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+/**
+ * 鎶借薄quartz璋冪敤
+ *
+ * @author ruoyi
+ */
+public abstract class AbstractQuartzJob implements Job
+{
+ private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
+
+ /**
+ * 绾跨▼鏈湴鍙橀噺
+ */
+ private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException
+ {
+ SysJob sysJob = new SysJob();
+ BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
+ try
+ {
+ before(context, sysJob);
+ if (sysJob != null)
+ {
+ doExecute(context, sysJob);
+ }
+ after(context, sysJob, null);
+ }
+ catch (Exception e)
+ {
+ log.error("浠诲姟鎵ц寮傚父 - 锛�", e);
+ after(context, sysJob, e);
+ }
+ }
+
+ /**
+ * 鎵ц鍓�
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ */
+ protected void before(JobExecutionContext context, SysJob sysJob)
+ {
+ threadLocal.set(new Date());
+ }
+
+ /**
+ * 鎵ц鍚�
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ */
+ protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
+ {
+ Date startTime = threadLocal.get();
+ threadLocal.remove();
+
+ final SysJobLog sysJobLog = new SysJobLog();
+ sysJobLog.setJobName(sysJob.getJobName());
+ sysJobLog.setJobGroup(sysJob.getJobGroup());
+ sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
+ sysJobLog.setStartTime(startTime);
+ sysJobLog.setStopTime(new Date());
+ long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
+ sysJobLog.setJobMessage(sysJobLog.getJobName() + " 鎬诲叡鑰楁椂锛�" + runMs + "姣");
+ if (e != null)
+ {
+ sysJobLog.setStatus(Constants.FAIL);
+ String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
+ sysJobLog.setExceptionInfo(errorMsg);
+ }
+ else
+ {
+ sysJobLog.setStatus(Constants.SUCCESS);
+ }
+
+ // 鍐欏叆鏁版嵁搴撳綋涓�
+ SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
+ }
+
+ /**
+ * 鎵ц鏂规硶锛岀敱瀛愮被閲嶈浇
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ * @throws Exception 鎵ц杩囩▼涓殑寮傚父
+ */
+ protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/CronUtils.java b/ycl-server/src/main/java/com/ycl/utils/quartz/CronUtils.java
new file mode 100644
index 0000000..468d682
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/CronUtils.java
@@ -0,0 +1,64 @@
+package com.ycl.utils.quartz;
+
+import org.quartz.CronExpression;
+
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * cron琛ㄨ揪寮忓伐鍏风被
+ *
+ * @author ruoyi
+ *
+ */
+public class CronUtils
+{
+ /**
+ * 杩斿洖涓�涓竷灏斿�间唬琛ㄤ竴涓粰瀹氱殑Cron琛ㄨ揪寮忕殑鏈夋晥鎬�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return boolean 琛ㄨ揪寮忔槸鍚︽湁鏁�
+ */
+ public static boolean isValid(String cronExpression)
+ {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 杩斿洖涓�涓瓧绗︿覆鍊�,琛ㄧず璇ユ秷鎭棤鏁圕ron琛ㄨ揪寮忕粰鍑烘湁鏁堟��
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return String 鏃犳晥鏃惰繑鍥炶〃杈惧紡閿欒鎻忚堪,濡傛灉鏈夋晥杩斿洖null
+ */
+ public static String getInvalidMessage(String cronExpression)
+ {
+ try
+ {
+ new CronExpression(cronExpression);
+ return null;
+ }
+ catch (ParseException pe)
+ {
+ return pe.getMessage();
+ }
+ }
+
+ /**
+ * 杩斿洖涓嬩竴涓墽琛屾椂闂存牴鎹粰瀹氱殑Cron琛ㄨ揪寮�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return Date 涓嬫Cron琛ㄨ揪寮忔墽琛屾椂闂�
+ */
+ public static Date getNextExecution(String cronExpression)
+ {
+ try
+ {
+ CronExpression cron = new CronExpression(cronExpression);
+ return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/JobInvokeUtil.java b/ycl-server/src/main/java/com/ycl/utils/quartz/JobInvokeUtil.java
new file mode 100644
index 0000000..64e47d1
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/JobInvokeUtil.java
@@ -0,0 +1,183 @@
+package com.ycl.utils.quartz;
+
+import com.ycl.system.domain.SysJob;
+import com.ycl.utils.StringUtils;
+import com.ycl.utils.spring.SpringUtils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 浠诲姟鎵ц宸ュ叿
+ *
+ * @author ruoyi
+ */
+public class JobInvokeUtil
+{
+ /**
+ * 鎵ц鏂规硶
+ *
+ * @param sysJob 绯荤粺浠诲姟
+ */
+ public static void invokeMethod(SysJob sysJob) throws Exception
+ {
+ String invokeTarget = sysJob.getInvokeTarget();
+ String beanName = getBeanName(invokeTarget);
+ String methodName = getMethodName(invokeTarget);
+ List<Object[]> methodParams = getMethodParams(invokeTarget);
+
+ if (!isValidClassName(beanName))
+ {
+ Object bean = SpringUtils.getBean(beanName);
+ invokeMethod(bean, methodName, methodParams);
+ }
+ else
+ {
+ Object bean = Class.forName(beanName).getDeclaredConstructor().newInstance();
+ invokeMethod(bean, methodName, methodParams);
+ }
+ }
+
+ /**
+ * 璋冪敤浠诲姟鏂规硶
+ *
+ * @param bean 鐩爣瀵硅薄
+ * @param methodName 鏂规硶鍚嶇О
+ * @param methodParams 鏂规硶鍙傛暟
+ */
+ private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
+ throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException
+ {
+ if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0)
+ {
+ Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams));
+ method.invoke(bean, getMethodParamsValue(methodParams));
+ }
+ else
+ {
+ Method method = bean.getClass().getMethod(methodName);
+ method.invoke(bean);
+ }
+ }
+
+ /**
+ * 鏍¢獙鏄惁涓轰负class鍖呭悕
+ *
+ * @param invokeTarget 鍚嶇О
+ * @return true鏄� false鍚�
+ */
+ public static boolean isValidClassName(String invokeTarget)
+ {
+ return StringUtils.countMatches(invokeTarget, ".") > 1;
+ }
+
+ /**
+ * 鑾峰彇bean鍚嶇О
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return bean鍚嶇О
+ */
+ public static String getBeanName(String invokeTarget)
+ {
+ String beanName = StringUtils.substringBefore(invokeTarget, "(");
+ return StringUtils.substringBeforeLast(beanName, ".");
+ }
+
+ /**
+ * 鑾峰彇bean鏂规硶
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return method鏂规硶
+ */
+ public static String getMethodName(String invokeTarget)
+ {
+ String methodName = StringUtils.substringBefore(invokeTarget, "(");
+ return StringUtils.substringAfterLast(methodName, ".");
+ }
+
+ /**
+ * 鑾峰彇method鏂规硶鍙傛暟鐩稿叧鍒楄〃
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return method鏂规硶鐩稿叧鍙傛暟鍒楄〃
+ */
+ public static List<Object[]> getMethodParams(String invokeTarget)
+ {
+ String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
+ if (StringUtils.isEmpty(methodStr))
+ {
+ return null;
+ }
+ String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
+ List<Object[]> classs = new LinkedList<>();
+ for (int i = 0; i < methodParams.length; i++)
+ {
+ String str = StringUtils.trimToEmpty(methodParams[i]);
+ // String瀛楃涓茬被鍨嬶紝浠�'鎴�"寮�澶�
+ if (StringUtils.startsWithAny(str, "'", "\""))
+ {
+ classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class });
+ }
+ // boolean甯冨皵绫诲瀷锛岀瓑浜巘rue鎴栬�協alse
+ else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
+ {
+ classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
+ }
+ // long闀挎暣褰紝浠缁撳熬
+ else if (StringUtils.endsWith(str, "L"))
+ {
+ classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class });
+ }
+ // double娴偣绫诲瀷锛屼互D缁撳熬
+ else if (StringUtils.endsWith(str, "D"))
+ {
+ classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class });
+ }
+ // 鍏朵粬绫诲瀷褰掔被涓烘暣褰�
+ else
+ {
+ classs.add(new Object[] { Integer.valueOf(str), Integer.class });
+ }
+ }
+ return classs;
+ }
+
+ /**
+ * 鑾峰彇鍙傛暟绫诲瀷
+ *
+ * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+ * @return 鍙傛暟绫诲瀷鍒楄〃
+ */
+ public static Class<?>[] getMethodParamsType(List<Object[]> methodParams)
+ {
+ Class<?>[] classs = new Class<?>[methodParams.size()];
+ int index = 0;
+ for (Object[] os : methodParams)
+ {
+ classs[index] = (Class<?>) os[1];
+ index++;
+ }
+ return classs;
+ }
+
+ /**
+ * 鑾峰彇鍙傛暟鍊�
+ *
+ * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+ * @return 鍙傛暟鍊煎垪琛�
+ */
+ public static Object[] getMethodParamsValue(List<Object[]> methodParams)
+ {
+ Object[] classs = new Object[methodParams.size()];
+ int index = 0;
+ for (Object[] os : methodParams)
+ {
+ classs[index] = (Object) os[0];
+ index++;
+ }
+ return classs;
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzDisallowConcurrentExecution.java b/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzDisallowConcurrentExecution.java
new file mode 100644
index 0000000..7287cce
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzDisallowConcurrentExecution.java
@@ -0,0 +1,21 @@
+package com.ycl.utils.quartz;
+
+import com.ycl.system.domain.SysJob;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堢姝㈠苟鍙戞墽琛岋級
+ *
+ * @author ruoyi
+ *
+ */
+@DisallowConcurrentExecution
+public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
+{
+ @Override
+ protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+ {
+ JobInvokeUtil.invokeMethod(sysJob);
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzJobExecution.java b/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzJobExecution.java
new file mode 100644
index 0000000..d91a1bc
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/QuartzJobExecution.java
@@ -0,0 +1,19 @@
+package com.ycl.utils.quartz;
+
+import com.ycl.system.domain.SysJob;
+import org.quartz.JobExecutionContext;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堝厑璁稿苟鍙戞墽琛岋級
+ *
+ * @author ruoyi
+ *
+ */
+public class QuartzJobExecution extends AbstractQuartzJob
+{
+ @Override
+ protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+ {
+ JobInvokeUtil.invokeMethod(sysJob);
+ }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/quartz/ScheduleUtils.java b/ycl-server/src/main/java/com/ycl/utils/quartz/ScheduleUtils.java
new file mode 100644
index 0000000..2ac0da7
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/utils/quartz/ScheduleUtils.java
@@ -0,0 +1,131 @@
+package com.ycl.utils.quartz;
+
+import com.ycl.exception.job.TaskException;
+import com.ycl.system.domain.SysJob;
+import com.ycl.utils.StringUtils;
+import com.ycl.utils.spring.SpringUtils;
+import constant.Constants;
+import constant.ScheduleConstants;
+import org.quartz.*;
+
+/**
+ * 瀹氭椂浠诲姟宸ュ叿绫�
+ *
+ * @author ruoyi
+ *
+ */
+public class ScheduleUtils
+{
+ /**
+ * 寰楀埌quartz浠诲姟绫�
+ *
+ * @param sysJob 鎵ц璁″垝
+ * @return 鍏蜂綋鎵ц浠诲姟绫�
+ */
+ private static Class<? extends Job> getQuartzJobClass(SysJob sysJob)
+ {
+ boolean isConcurrent = "0".equals(sysJob.getConcurrent());
+ return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
+ }
+
+ /**
+ * 鏋勫缓浠诲姟瑙﹀彂瀵硅薄
+ */
+ public static TriggerKey getTriggerKey(Long jobId, String jobGroup)
+ {
+ return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+ }
+
+ /**
+ * 鏋勫缓浠诲姟閿璞�
+ */
+ public static JobKey getJobKey(Long jobId, String jobGroup)
+ {
+ return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+ }
+
+ /**
+ * 鍒涘缓瀹氭椂浠诲姟
+ */
+ public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
+ {
+ Class<? extends Job> jobClass = getQuartzJobClass(job);
+ // 鏋勫缓job淇℃伅
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();
+
+ // 琛ㄨ揪寮忚皟搴︽瀯寤哄櫒
+ CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+ cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
+
+ // 鎸夋柊鐨刢ronExpression琛ㄨ揪寮忔瀯寤轰竴涓柊鐨則rigger
+ CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
+ .withSchedule(cronScheduleBuilder).build();
+
+ // 鏀惧叆鍙傛暟锛岃繍琛屾椂鐨勬柟娉曞彲浠ヨ幏鍙�
+ jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
+
+ // 鍒ゆ柇鏄惁瀛樺湪
+ if (scheduler.checkExists(getJobKey(jobId, jobGroup)))
+ {
+ // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+ scheduler.deleteJob(getJobKey(jobId, jobGroup));
+ }
+
+ // 鍒ゆ柇浠诲姟鏄惁杩囨湡
+ if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression())))
+ {
+ // 鎵ц璋冨害浠诲姟
+ scheduler.scheduleJob(jobDetail, trigger);
+ }
+
+ // 鏆傚仠浠诲姟
+ if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+ {
+ scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ }
+
+ /**
+ * 璁剧疆瀹氭椂浠诲姟绛栫暐
+ */
+ public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
+ throws TaskException
+ {
+ switch (job.getMisfirePolicy())
+ {
+ case ScheduleConstants.MISFIRE_DEFAULT:
+ return cb;
+ case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
+ return cb.withMisfireHandlingInstructionIgnoreMisfires();
+ case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
+ return cb.withMisfireHandlingInstructionFireAndProceed();
+ case ScheduleConstants.MISFIRE_DO_NOTHING:
+ return cb.withMisfireHandlingInstructionDoNothing();
+ default:
+ throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
+ + "' cannot be used in cron schedule tasks", TaskException.Code.CONFIG_ERROR);
+ }
+ }
+
+ /**
+ * 妫�鏌ュ寘鍚嶆槸鍚︿负鐧藉悕鍗曢厤缃�
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return 缁撴灉
+ */
+ public static boolean whiteList(String invokeTarget)
+ {
+ String packageName = StringUtils.substringBefore(invokeTarget, "(");
+ int count = StringUtils.countMatches(packageName, ".");
+ if (count > 1)
+ {
+ return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
+ }
+ Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
+ String beanPackageName = obj.getClass().getPackage().getName();
+ return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
+ && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
+ }
+}
diff --git a/ycl-server/src/main/resources/mapper/system/SysJobLogMapper.xml b/ycl-server/src/main/resources/mapper/system/SysJobLogMapper.xml
new file mode 100644
index 0000000..2f753b2
--- /dev/null
+++ b/ycl-server/src/main/resources/mapper/system/SysJobLogMapper.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ycl.system.mapper.SysJobLogMapper">
+
+ <resultMap type="SysJobLog" id="SysJobLogResult">
+ <id property="jobLogId" column="job_log_id" />
+ <result property="jobName" column="job_name" />
+ <result property="jobGroup" column="job_group" />
+ <result property="invokeTarget" column="invoke_target" />
+ <result property="jobMessage" column="job_message" />
+ <result property="status" column="status" />
+ <result property="exceptionInfo" column="exception_info" />
+ <result property="createTime" column="create_time" />
+ </resultMap>
+
+ <sql id="selectJobLogVo">
+ select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time
+ from sys_job_log
+ </sql>
+
+ <select id="selectJobLogList" parameterType="SysJobLog" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ <where>
+ <if test="jobName != null and jobName != ''">
+ AND job_name like concat('%', #{jobName}, '%')
+ </if>
+ <if test="jobGroup != null and jobGroup != ''">
+ AND job_group = #{jobGroup}
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="invokeTarget != null and invokeTarget != ''">
+ AND invoke_target like concat('%', #{invokeTarget}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ and date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
+ </if>
+ </where>
+ order by create_time desc
+ </select>
+
+ <select id="selectJobLogAll" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ </select>
+
+ <select id="selectJobLogById" parameterType="Long" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ where job_log_id = #{jobLogId}
+ </select>
+
+ <delete id="deleteJobLogById" parameterType="Long">
+ delete from sys_job_log where job_log_id = #{jobLogId}
+ </delete>
+
+ <delete id="deleteJobLogByIds" parameterType="Long">
+ delete from sys_job_log where job_log_id in
+ <foreach collection="array" item="jobLogId" open="(" separator="," close=")">
+ #{jobLogId}
+ </foreach>
+ </delete>
+
+ <update id="cleanJobLog">
+ truncate table sys_job_log
+ </update>
+
+ <insert id="insertJobLog" parameterType="SysJobLog">
+ insert into sys_job_log(
+ <if test="jobLogId != null and jobLogId != 0">job_log_id,</if>
+ <if test="jobName != null and jobName != ''">job_name,</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ <if test="jobMessage != null and jobMessage != ''">job_message,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="exceptionInfo != null and exceptionInfo != ''">exception_info,</if>
+ create_time
+ )values(
+ <if test="jobLogId != null and jobLogId != 0">#{jobLogId},</if>
+ <if test="jobName != null and jobName != ''">#{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ <if test="jobMessage != null and jobMessage != ''">#{jobMessage},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="exceptionInfo != null and exceptionInfo != ''">#{exceptionInfo},</if>
+ sysdate()
+ )
+ </insert>
+
+</mapper>
diff --git a/ycl-server/src/main/resources/mapper/system/SysJobMapper.xml b/ycl-server/src/main/resources/mapper/system/SysJobMapper.xml
new file mode 100644
index 0000000..685ec2f
--- /dev/null
+++ b/ycl-server/src/main/resources/mapper/system/SysJobMapper.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ycl.system.mapper.SysJobMapper">
+
+ <resultMap type="SysJob" id="SysJobResult">
+ <id property="jobId" column="job_id" />
+ <result property="jobName" column="job_name" />
+ <result property="jobGroup" column="job_group" />
+ <result property="invokeTarget" column="invoke_target" />
+ <result property="cronExpression" column="cron_expression" />
+ <result property="misfirePolicy" column="misfire_policy" />
+ <result property="concurrent" column="concurrent" />
+ <result property="status" column="status" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectJobVo">
+ select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark
+ from sys_job
+ </sql>
+
+ <select id="selectJobList" parameterType="SysJob" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ <where>
+ <if test="jobName != null and jobName != ''">
+ AND job_name like concat('%', #{jobName}, '%')
+ </if>
+ <if test="jobGroup != null and jobGroup != ''">
+ AND job_group = #{jobGroup}
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="invokeTarget != null and invokeTarget != ''">
+ AND invoke_target like concat('%', #{invokeTarget}, '%')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectJobAll" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ </select>
+
+ <select id="selectJobById" parameterType="Long" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ where job_id = #{jobId}
+ </select>
+
+ <delete id="deleteJobById" parameterType="Long">
+ delete from sys_job where job_id = #{jobId}
+ </delete>
+
+ <delete id="deleteJobByIds" parameterType="Long">
+ delete from sys_job where job_id in
+ <foreach collection="array" item="jobId" open="(" separator="," close=")">
+ #{jobId}
+ </foreach>
+ </delete>
+
+ <update id="updateJob" parameterType="SysJob">
+ update sys_job
+ <set>
+ <if test="jobName != null and jobName != ''">job_name = #{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group = #{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target = #{invokeTarget},</if>
+ <if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
+ <if test="concurrent != null and concurrent != ''">concurrent = #{concurrent},</if>
+ <if test="status !=null">status = #{status},</if>
+ <if test="remark != null and remark != ''">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where job_id = #{jobId}
+ </update>
+
+ <insert id="insertJob" parameterType="SysJob" useGeneratedKeys="true" keyProperty="jobId">
+ insert into sys_job(
+ <if test="jobId != null and jobId != 0">job_id,</if>
+ <if test="jobName != null and jobName != ''">job_name,</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ <if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
+ <if test="concurrent != null and concurrent != ''">concurrent,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="jobId != null and jobId != 0">#{jobId},</if>
+ <if test="jobName != null and jobName != ''">#{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ <if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
+ <if test="concurrent != null and concurrent != ''">#{concurrent},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+</mapper>
--
Gitblit v1.8.0