From 62abc9a5005ee7467934b21c449fd95b195c3ccd Mon Sep 17 00:00:00 2001
From: stone <827672943@qq.com>
Date: Tue, 9 May 2023 09:05:33 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AE=9A=E6=97=B6=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/psdc/constant/Constants.java | 10 +
.../com/psdc/constant/ScheduleConstants.java | 50 ++++
.../com/psdc/exception/job/TaskException.java | 34 +++
psdc-quartz/pom.xml | 40 +++
.../quartz/controller/SysJobController.java | 185 +++++++++++++
.../controller/SysJobLogController.java | 92 ++++++
.../java/com/psdc/quartz/domain/SysJob.java | 171 ++++++++++++
.../com/psdc/quartz/domain/SysJobLog.java | 155 +++++++++++
.../psdc/quartz/mapper/SysJobLogMapper.java | 64 +++++
.../com/psdc/quartz/mapper/SysJobMapper.java | 67 +++++
.../quartz/service/ISysJobLogService.java | 56 ++++
.../psdc/quartz/service/ISysJobService.java | 102 +++++++
.../service/impl/SysJobLogServiceImpl.java | 87 ++++++
.../service/impl/SysJobServiceImpl.java | 261 ++++++++++++++++++
.../java/com/psdc/quartz/task/RyTask.java | 28 ++
.../psdc/quartz/util/AbstractQuartzJob.java | 107 +++++++
.../java/com/psdc/quartz/util/CronUtils.java | 63 +++++
.../com/psdc/quartz/util/JobInvokeUtil.java | 182 ++++++++++++
.../QuartzDisallowConcurrentExecution.java | 21 ++
.../psdc/quartz/util/QuartzJobExecution.java | 19 ++
.../com/psdc/quartz/util/ScheduleUtils.java | 141 ++++++++++
.../mapper/quartz/SysJobLogMapper.xml | 93 +++++++
.../resources/mapper/quartz/SysJobMapper.xml | 111 ++++++++
23 files changed, 2139 insertions(+)
create mode 100644 psdc-common/src/main/java/com/psdc/constant/ScheduleConstants.java
create mode 100644 psdc-common/src/main/java/com/psdc/exception/job/TaskException.java
create mode 100644 psdc-quartz/pom.xml
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobController.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobLogController.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJob.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJobLog.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobLogMapper.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobMapper.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobLogService.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobService.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobLogServiceImpl.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobServiceImpl.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/task/RyTask.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/AbstractQuartzJob.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/CronUtils.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/JobInvokeUtil.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/QuartzDisallowConcurrentExecution.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/QuartzJobExecution.java
create mode 100644 psdc-quartz/src/main/java/com/psdc/quartz/util/ScheduleUtils.java
create mode 100644 psdc-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
create mode 100644 psdc-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
diff --git a/psdc-common/src/main/java/com/psdc/constant/Constants.java b/psdc-common/src/main/java/com/psdc/constant/Constants.java
index e70ac3c..e9ea5a6 100644
--- a/psdc-common/src/main/java/com/psdc/constant/Constants.java
+++ b/psdc-common/src/main/java/com/psdc/constant/Constants.java
@@ -129,4 +129,14 @@ public class Constants
*/
public static final String LOOKUP_LDAPS = "ldaps:";
+ /**
+ * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+ */
+ public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
+
+ /**
+ * 定时任务违规的字符
+ */
+ public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+ "org.springframework", "org.apache", "com.psdc.common.utils.file", "com.psdc.common.config" };
}
diff --git a/psdc-common/src/main/java/com/psdc/constant/ScheduleConstants.java b/psdc-common/src/main/java/com/psdc/constant/ScheduleConstants.java
new file mode 100644
index 0000000..d97553b
--- /dev/null
+++ b/psdc-common/src/main/java/com/psdc/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.psdc.constant;
+
+/**
+ * 任务调度通用常量
+ *
+ * @author
+ */
+public class ScheduleConstants
+{
+ public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+ /** 执行目标key */
+ public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+ /** 默认 */
+ public static final String MISFIRE_DEFAULT = "0";
+
+ /** 立即触发执行 */
+ public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+ /** 触发一次执行 */
+ public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+ /** 不触发立即执行 */
+ public static final String MISFIRE_DO_NOTHING = "3";
+
+ public enum Status
+ {
+ /**
+ * 正常
+ */
+ NORMAL("0"),
+ /**
+ * 暂停
+ */
+ PAUSE("1");
+
+ private String value;
+
+ private Status(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+}
diff --git a/psdc-common/src/main/java/com/psdc/exception/job/TaskException.java b/psdc-common/src/main/java/com/psdc/exception/job/TaskException.java
new file mode 100644
index 0000000..1350eb2
--- /dev/null
+++ b/psdc-common/src/main/java/com/psdc/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.psdc.exception.job;
+
+/**
+ * 计划策略异常
+ *
+ * @author
+ */
+public class TaskException extends Exception
+{
+ private static final long serialVersionUID = 1L;
+
+ private Code code;
+
+ public TaskException(String msg, Code code)
+ {
+ this(msg, code, null);
+ }
+
+ public TaskException(String msg, Code code, Exception nestedEx)
+ {
+ super(msg, nestedEx);
+ this.code = code;
+ }
+
+ public Code getCode()
+ {
+ return code;
+ }
+
+ public enum Code
+ {
+ TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+ }
+}
\ No newline at end of file
diff --git a/psdc-quartz/pom.xml b/psdc-quartz/pom.xml
new file mode 100644
index 0000000..ef2fc6c
--- /dev/null
+++ b/psdc-quartz/pom.xml
@@ -0,0 +1,40 @@
+
+
+
+ psdc
+ com.psdc
+ 0.0.1
+
+ 4.0.0
+
+ energy-quartz
+
+
+ quartz定时任务
+
+
+
+
+
+
+ org.quartz-scheduler
+ quartz
+
+
+ com.mchange
+ c3p0
+
+
+
+
+
+
+ com.psdc
+ psdc-common
+
+
+
+
+
\ No newline at end of file
diff --git a/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobController.java b/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobController.java
new file mode 100644
index 0000000..5306d87
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobController.java
@@ -0,0 +1,185 @@
+package com.psdc.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.psdc.annotation.Log;
+import com.psdc.constant.Constants;
+import com.psdc.core.controller.BaseController;
+import com.psdc.core.domain.AjaxResult;
+import com.psdc.core.page.TableDataInfo;
+import com.psdc.enums.BusinessType;
+import com.psdc.exception.job.TaskException;
+import com.psdc.utils.StringUtils;
+import com.psdc.utils.poi.ExcelUtil;
+import com.psdc.quartz.domain.SysJob;
+import com.psdc.quartz.service.ISysJobService;
+import com.psdc.quartz.util.CronUtils;
+import com.psdc.quartz.util.ScheduleUtils;
+
+/**
+ * 调度任务信息操作处理
+ *
+ * @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 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 list = jobService.selectJobList(sysJob);
+ ExcelUtil util = new ExcelUtil(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() + "'失败,Cron表达式不正确");
+ }
+ 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() + "'失败,Cron表达式不正确");
+ }
+ 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/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobLogController.java b/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobLogController.java
new file mode 100644
index 0000000..ea7c56a
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/controller/SysJobLogController.java
@@ -0,0 +1,92 @@
+package com.psdc.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.psdc.annotation.Log;
+import com.psdc.core.controller.BaseController;
+import com.psdc.core.domain.AjaxResult;
+import com.psdc.core.page.TableDataInfo;
+import com.psdc.enums.BusinessType;
+import com.psdc.utils.poi.ExcelUtil;
+import com.psdc.quartz.domain.SysJobLog;
+import com.psdc.quartz.service.ISysJobLogService;
+
+/**
+ * 调度日志操作处理
+ *
+ * @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 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 list = jobLogService.selectJobLogList(sysJobLog);
+ ExcelUtil util = new ExcelUtil(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/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJob.java b/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJob.java
new file mode 100644
index 0000000..edbdb8c
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJob.java
@@ -0,0 +1,171 @@
+package com.psdc.quartz.domain;
+
+import java.util.Date;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.psdc.annotation.Excel;
+import com.psdc.annotation.Excel.ColumnType;
+import com.psdc.constant.ScheduleConstants;
+import com.psdc.core.domain.BaseEntity;
+import com.psdc.utils.StringUtils;
+import com.psdc.quartz.util.CronUtils;
+
+/**
+ * 定时任务调度表 sys_job
+ *
+ * @author ruoyi
+ */
+public class SysJob extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 任务ID */
+ @Excel(name = "任务序号", cellType = 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正常 1暂停) */
+ @Excel(name = "任务状态", readConverterExp = "0=正常,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/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJobLog.java b/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJobLog.java
new file mode 100644
index 0000000..68c7df6
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/domain/SysJobLog.java
@@ -0,0 +1,155 @@
+package com.psdc.quartz.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.psdc.annotation.Excel;
+import com.psdc.core.domain.BaseEntity;
+
+/**
+ * 定时任务调度日志表 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正常 1失败) */
+ @Excel(name = "执行状态", readConverterExp = "0=正常,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/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobLogMapper.java b/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..5793698
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobLogMapper.java
@@ -0,0 +1,64 @@
+package com.psdc.quartz.mapper;
+
+import java.util.List;
+import com.psdc.quartz.domain.SysJobLog;
+
+/**
+ * 调度任务日志信息 数据层
+ *
+ * @author ruoyi
+ */
+public interface SysJobLogMapper
+{
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 查询所有调度任务日志
+ *
+ * @return 调度任务日志列表
+ */
+ public List 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/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobMapper.java b/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobMapper.java
new file mode 100644
index 0000000..f688976
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/mapper/SysJobMapper.java
@@ -0,0 +1,67 @@
+package com.psdc.quartz.mapper;
+
+import java.util.List;
+import com.psdc.quartz.domain.SysJob;
+
+/**
+ * 调度任务信息 数据层
+ *
+ * @author ruoyi
+ */
+public interface SysJobMapper
+{
+ /**
+ * 查询调度任务日志集合
+ *
+ * @param job 调度信息
+ * @return 操作日志集合
+ */
+ public List selectJobList(SysJob job);
+
+ /**
+ * 查询所有调度任务
+ *
+ * @return 调度任务列表
+ */
+ public List 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/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobLogService.java b/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobLogService.java
new file mode 100644
index 0000000..3c1473b
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobLogService.java
@@ -0,0 +1,56 @@
+package com.psdc.quartz.service;
+
+import java.util.List;
+import com.psdc.quartz.domain.SysJobLog;
+
+/**
+ * 定时任务调度日志信息信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface ISysJobLogService
+{
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List 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/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobService.java b/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobService.java
new file mode 100644
index 0000000..ae84196
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/service/ISysJobService.java
@@ -0,0 +1,102 @@
+package com.psdc.quartz.service;
+
+import java.util.List;
+import org.quartz.SchedulerException;
+import com.psdc.exception.job.TaskException;
+import com.psdc.quartz.domain.SysJob;
+
+/**
+ * 定时任务调度信息信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface ISysJobService
+{
+ /**
+ * 获取quartz调度器的计划任务
+ *
+ * @param job 调度信息
+ * @return 调度任务集合
+ */
+ public List 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;
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @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/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobLogServiceImpl.java b/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..2c1f954
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobLogServiceImpl.java
@@ -0,0 +1,87 @@
+package com.psdc.quartz.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.psdc.quartz.domain.SysJobLog;
+import com.psdc.quartz.mapper.SysJobLogMapper;
+import com.psdc.quartz.service.ISysJobLogService;
+
+/**
+ * 定时任务调度日志信息 服务层
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysJobLogServiceImpl implements ISysJobLogService
+{
+ @Autowired
+ private SysJobLogMapper jobLogMapper;
+
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ @Override
+ public List 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/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobServiceImpl.java b/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobServiceImpl.java
new file mode 100644
index 0000000..9e05179
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/service/impl/SysJobServiceImpl.java
@@ -0,0 +1,261 @@
+package com.psdc.quartz.service.impl;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+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 com.psdc.constant.ScheduleConstants;
+import com.psdc.exception.job.TaskException;
+import com.psdc.quartz.domain.SysJob;
+import com.psdc.quartz.mapper.SysJobMapper;
+import com.psdc.quartz.service.ISysJobService;
+import com.psdc.quartz.util.CronUtils;
+import com.psdc.quartz.util.ScheduleUtils;
+
+/**
+ * 定时任务调度信息 服务层
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysJobServiceImpl implements ISysJobService
+{
+ @Autowired
+ private Scheduler scheduler;
+
+ @Autowired
+ private SysJobMapper jobMapper;
+
+ /**
+ * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
+ */
+ @PostConstruct
+ public void init() throws SchedulerException, TaskException
+ {
+ scheduler.clear();
+ List jobList = jobMapper.selectJobAll();
+ for (SysJob job : jobList)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ }
+
+ /**
+ * 获取quartz调度器的计划任务列表
+ *
+ * @param job 调度信息
+ * @return
+ */
+ @Override
+ public List 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;
+ }
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @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/psdc-quartz/src/main/java/com/psdc/quartz/task/RyTask.java b/psdc-quartz/src/main/java/com/psdc/quartz/task/RyTask.java
new file mode 100644
index 0000000..5ad0e14
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.psdc.quartz.task;
+
+import org.springframework.stereotype.Component;
+import com.psdc.utils.StringUtils;
+
+/**
+ * 定时任务调度测试
+ *
+ * @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/psdc-quartz/src/main/java/com/psdc/quartz/util/AbstractQuartzJob.java b/psdc-quartz/src/main/java/com/psdc/quartz/util/AbstractQuartzJob.java
new file mode 100644
index 0000000..6065849
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/util/AbstractQuartzJob.java
@@ -0,0 +1,107 @@
+package com.psdc.quartz.util;
+
+import java.util.Date;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.psdc.constant.Constants;
+import com.psdc.constant.ScheduleConstants;
+import com.psdc.utils.ExceptionUtil;
+import com.psdc.utils.StringUtils;
+import com.psdc.utils.bean.BeanUtils;
+import com.psdc.utils.spring.SpringUtils;
+import com.psdc.quartz.domain.SysJob;
+import com.psdc.quartz.domain.SysJobLog;
+import com.psdc.quartz.service.ISysJobLogService;
+
+/**
+ * 抽象quartz调用
+ *
+ * @author ruoyi
+ */
+public abstract class AbstractQuartzJob implements Job
+{
+ private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
+
+ /**
+ * 线程本地变量
+ */
+ private static ThreadLocal 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/psdc-quartz/src/main/java/com/psdc/quartz/util/CronUtils.java b/psdc-quartz/src/main/java/com/psdc/quartz/util/CronUtils.java
new file mode 100644
index 0000000..32859a8
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/util/CronUtils.java
@@ -0,0 +1,63 @@
+package com.psdc.quartz.util;
+
+import java.text.ParseException;
+import java.util.Date;
+import org.quartz.CronExpression;
+
+/**
+ * cron表达式工具类
+ *
+ * @author ruoyi
+ *
+ */
+public class CronUtils
+{
+ /**
+ * 返回一个布尔值代表一个给定的Cron表达式的有效性
+ *
+ * @param cronExpression Cron表达式
+ * @return boolean 表达式是否有效
+ */
+ public static boolean isValid(String cronExpression)
+ {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 返回一个字符串值,表示该消息无效Cron表达式给出有效性
+ *
+ * @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/psdc-quartz/src/main/java/com/psdc/quartz/util/JobInvokeUtil.java b/psdc-quartz/src/main/java/com/psdc/quartz/util/JobInvokeUtil.java
new file mode 100644
index 0000000..46d95ad
--- /dev/null
+++ b/psdc-quartz/src/main/java/com/psdc/quartz/util/JobInvokeUtil.java
@@ -0,0 +1,182 @@
+package com.psdc.quartz.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import com.psdc.utils.StringUtils;
+import com.psdc.utils.spring.SpringUtils;
+import com.psdc.quartz.domain.SysJob;
+
+/**
+ * 任务执行工具
+ *
+ * @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