若依 3.0
This commit is contained in:
		| @@ -0,0 +1,57 @@ | ||||
| package com.ruoyi.quartz.config; | ||||
|  | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.scheduling.quartz.SchedulerFactoryBean; | ||||
| import javax.sql.DataSource; | ||||
| import java.util.Properties; | ||||
|  | ||||
| /** | ||||
|  * 定时任务配置 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| @Configuration | ||||
| public class ScheduleConfig | ||||
| { | ||||
|     @Bean | ||||
|     public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) | ||||
|     { | ||||
|         SchedulerFactoryBean factory = new SchedulerFactoryBean(); | ||||
|         factory.setDataSource(dataSource); | ||||
|  | ||||
|         // quartz参数 | ||||
|         Properties prop = new Properties(); | ||||
|         prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); | ||||
|         prop.put("org.quartz.scheduler.instanceId", "AUTO"); | ||||
|         // 线程池配置 | ||||
|         prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); | ||||
|         prop.put("org.quartz.threadPool.threadCount", "20"); | ||||
|         prop.put("org.quartz.threadPool.threadPriority", "5"); | ||||
|         // JobStore配置 | ||||
|         prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); | ||||
|         // 集群配置 | ||||
|         prop.put("org.quartz.jobStore.isClustered", "true"); | ||||
|         prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); | ||||
|         prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); | ||||
|         prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); | ||||
|  | ||||
|         // sqlserver 启用 | ||||
|         // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); | ||||
|         prop.put("org.quartz.jobStore.misfireThreshold", "12000"); | ||||
|         prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); | ||||
|         factory.setQuartzProperties(prop); | ||||
|  | ||||
|         factory.setSchedulerName("RuoyiScheduler"); | ||||
|         // 延时启动 | ||||
|         factory.setStartupDelay(1); | ||||
|         factory.setApplicationContextSchedulerContextKey("applicationContextKey"); | ||||
|         // 可选,QuartzScheduler | ||||
|         // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 | ||||
|         factory.setOverwriteExistingJobs(true); | ||||
|         // 设置自动启动,默认为true | ||||
|         factory.setAutoStartup(true); | ||||
|  | ||||
|         return factory; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,142 @@ | ||||
| package com.ruoyi.quartz.controller; | ||||
|  | ||||
| import java.util.List; | ||||
| 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.ruoyi.common.annotation.Log; | ||||
| import com.ruoyi.common.core.controller.BaseController; | ||||
| import com.ruoyi.common.core.domain.AjaxResult; | ||||
| import com.ruoyi.common.core.page.TableDataInfo; | ||||
| import com.ruoyi.common.enums.BusinessType; | ||||
| import com.ruoyi.common.exception.job.TaskException; | ||||
| import com.ruoyi.common.utils.SecurityUtils; | ||||
| import com.ruoyi.common.utils.poi.ExcelUtil; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
| import com.ruoyi.quartz.service.ISysJobService; | ||||
| import com.ruoyi.quartz.util.CronUtils; | ||||
|  | ||||
| /** | ||||
|  * 调度任务信息操作处理 | ||||
|  *  | ||||
|  * @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) | ||||
|     @GetMapping("/export") | ||||
|     public AjaxResult export(SysJob sysJob) | ||||
|     { | ||||
|         List<SysJob> list = jobService.selectJobList(sysJob); | ||||
|         ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class); | ||||
|         return util.exportExcel(list, "定时任务"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取定时任务详细信息 | ||||
|      */ | ||||
|     @PreAuthorize("@ss.hasPermi('monitor:job:query')") | ||||
|     @GetMapping(value = "/{jobId}") | ||||
|     public AjaxResult getInfo(@PathVariable("jobId") Long jobId) | ||||
|     { | ||||
|         return AjaxResult.success(jobService.selectJobById(jobId)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增定时任务 | ||||
|      */ | ||||
|     @PreAuthorize("@ss.hasPermi('monitor:job:add')") | ||||
|     @Log(title = "定时任务", businessType = BusinessType.INSERT) | ||||
|     @PostMapping | ||||
|     public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException | ||||
|     { | ||||
|         if (!CronUtils.isValid(sysJob.getCronExpression())) | ||||
|         { | ||||
|             return AjaxResult.error("cron表达式不正确"); | ||||
|         } | ||||
|         sysJob.setCreateBy(SecurityUtils.getUsername()); | ||||
|         return toAjax(jobService.insertJob(sysJob)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 修改定时任务 | ||||
|      */ | ||||
|     @PreAuthorize("@ss.hasPermi('monitor:job:edit')") | ||||
|     @Log(title = "定时任务", businessType = BusinessType.UPDATE) | ||||
|     @PutMapping | ||||
|     public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException | ||||
|     { | ||||
|         if (!CronUtils.isValid(sysJob.getCronExpression())) | ||||
|         { | ||||
|             return AjaxResult.error("cron表达式不正确"); | ||||
|         } | ||||
|         sysJob.setUpdateBy(SecurityUtils.getUsername()); | ||||
|         return toAjax(jobService.updateJob(sysJob)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 定时任务状态修改 | ||||
|      */ | ||||
|     @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 | ||||
|     { | ||||
|         jobService.run(job); | ||||
|         return AjaxResult.success(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除定时任务 | ||||
|      */ | ||||
|     @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 AjaxResult.success(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,90 @@ | ||||
| package com.ruoyi.quartz.controller; | ||||
|  | ||||
| import java.util.List; | ||||
| 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.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import com.ruoyi.common.annotation.Log; | ||||
| import com.ruoyi.common.core.controller.BaseController; | ||||
| import com.ruoyi.common.core.domain.AjaxResult; | ||||
| import com.ruoyi.common.core.page.TableDataInfo; | ||||
| import com.ruoyi.common.enums.BusinessType; | ||||
| import com.ruoyi.common.utils.poi.ExcelUtil; | ||||
| import com.ruoyi.quartz.domain.SysJobLog; | ||||
| import com.ruoyi.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<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog); | ||||
|         return getDataTable(list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导出定时任务调度日志列表 | ||||
|      */ | ||||
|     @PreAuthorize("@ss.hasPermi('monitor:job:export')") | ||||
|     @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) | ||||
|     @GetMapping("/export") | ||||
|     public AjaxResult export(SysJobLog sysJobLog) | ||||
|     { | ||||
|         List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog); | ||||
|         ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class); | ||||
|         return util.exportExcel(list, "调度日志"); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * 根据调度编号获取详细信息 | ||||
|      */ | ||||
|     @PreAuthorize("@ss.hasPermi('monitor:job:query')") | ||||
|     @GetMapping(value = "/{configId}") | ||||
|     public AjaxResult getInfo(@PathVariable Long jobLogId) | ||||
|     { | ||||
|         return AjaxResult.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 AjaxResult.success(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										172
									
								
								ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| package com.ruoyi.quartz.domain; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| 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.ruoyi.common.annotation.Excel; | ||||
| import com.ruoyi.common.annotation.Excel.ColumnType; | ||||
| import com.ruoyi.common.constant.ScheduleConstants; | ||||
| import com.ruoyi.common.core.domain.BaseEntity; | ||||
| import com.ruoyi.common.utils.StringUtils; | ||||
| import com.ruoyi.quartz.util.CronUtils; | ||||
|  | ||||
| /** | ||||
|  * 定时任务调度表 sys_job | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| public class SysJob extends BaseEntity implements Serializable | ||||
| { | ||||
|     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 = 1000, 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(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,155 @@ | ||||
| package com.ruoyi.quartz.domain; | ||||
|  | ||||
| import java.util.Date; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | ||||
| import org.apache.commons.lang3.builder.ToStringStyle; | ||||
| import com.ruoyi.common.annotation.Excel; | ||||
| import com.ruoyi.common.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(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,64 @@ | ||||
| package com.ruoyi.quartz.mapper; | ||||
|  | ||||
| import java.util.List; | ||||
| import com.ruoyi.quartz.domain.SysJobLog; | ||||
|  | ||||
| /** | ||||
|  * 调度任务日志信息 数据层 | ||||
|  *  | ||||
|  * @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(); | ||||
| } | ||||
| @@ -0,0 +1,67 @@ | ||||
| package com.ruoyi.quartz.mapper; | ||||
|  | ||||
| import java.util.List; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
|  | ||||
| /** | ||||
|  * 调度任务信息 数据层 | ||||
|  *  | ||||
|  * @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); | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| package com.ruoyi.quartz.service; | ||||
|  | ||||
| import java.util.List; | ||||
| import com.ruoyi.quartz.domain.SysJobLog; | ||||
|  | ||||
| /** | ||||
|  * 定时任务调度日志信息信息 服务层 | ||||
|  *  | ||||
|  * @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(); | ||||
| } | ||||
| @@ -0,0 +1,102 @@ | ||||
| package com.ruoyi.quartz.service; | ||||
|  | ||||
| import java.util.List; | ||||
| import org.quartz.SchedulerException; | ||||
| import com.ruoyi.common.exception.job.TaskException; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
|  | ||||
| /** | ||||
|  * 定时任务调度信息信息 服务层 | ||||
|  *  | ||||
|  * @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; | ||||
|  | ||||
|     /** | ||||
|      * 删除任务后,所对应的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 void 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); | ||||
| } | ||||
| @@ -0,0 +1,87 @@ | ||||
| package com.ruoyi.quartz.service.impl; | ||||
|  | ||||
| import java.util.List; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
| import com.ruoyi.quartz.domain.SysJobLog; | ||||
| import com.ruoyi.quartz.mapper.SysJobLogMapper; | ||||
| import com.ruoyi.quartz.service.ISysJobLogService; | ||||
|  | ||||
| /** | ||||
|  * 定时任务调度日志信息 服务层 | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  */ | ||||
| @Service | ||||
| public class SysJobLogServiceImpl implements ISysJobLogService | ||||
| { | ||||
|     @Autowired | ||||
|     private 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(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,254 @@ | ||||
| package com.ruoyi.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.ruoyi.common.constant.ScheduleConstants; | ||||
| import com.ruoyi.common.exception.job.TaskException; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
| import com.ruoyi.quartz.mapper.SysJobMapper; | ||||
| import com.ruoyi.quartz.service.ISysJobService; | ||||
| import com.ruoyi.quartz.util.CronUtils; | ||||
| import com.ruoyi.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<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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     public void deleteJobByIds(Long[] jobIds) throws SchedulerException | ||||
|     { | ||||
|         for (Long jobId : jobIds) | ||||
|         { | ||||
|             SysJob job = jobMapper.selectJobById(jobId); | ||||
|             deleteJob(job); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 任务调度状态修改 | ||||
|      *  | ||||
|      * @param job 调度信息 | ||||
|      */ | ||||
|     @Override | ||||
|     @Transactional | ||||
|     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 | ||||
|     public void run(SysJob job) throws SchedulerException | ||||
|     { | ||||
|         Long jobId = job.getJobId(); | ||||
|         String jobGroup = job.getJobGroup(); | ||||
|         SysJob properties = selectJobById(job.getJobId()); | ||||
|         // 参数 | ||||
|         JobDataMap dataMap = new JobDataMap(); | ||||
|         dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); | ||||
|         scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增任务 | ||||
|      *  | ||||
|      * @param job 调度信息 调度信息 | ||||
|      */ | ||||
|     @Override | ||||
|     @Transactional | ||||
|     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 | ||||
|     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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package com.ruoyi.quartz.task; | ||||
|  | ||||
| import org.springframework.stereotype.Component; | ||||
| import com.ruoyi.common.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("执行无参方法"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,107 @@ | ||||
| package com.ruoyi.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.ruoyi.common.constant.Constants; | ||||
| import com.ruoyi.common.constant.ScheduleConstants; | ||||
| import com.ruoyi.common.utils.ExceptionUtil; | ||||
| import com.ruoyi.common.utils.StringUtils; | ||||
| import com.ruoyi.common.utils.bean.BeanUtils; | ||||
| import com.ruoyi.common.utils.spring.SpringUtils; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
| import com.ruoyi.quartz.domain.SysJobLog; | ||||
| import com.ruoyi.quartz.service.ISysJobLogService; | ||||
|  | ||||
| /** | ||||
|  * 抽象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 sysScheduleJob 系统计划任务 | ||||
|      */ | ||||
|     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; | ||||
| } | ||||
| @@ -0,0 +1,63 @@ | ||||
| package com.ruoyi.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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,182 @@ | ||||
| package com.ruoyi.quartz.util; | ||||
|  | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| import com.ruoyi.common.utils.StringUtils; | ||||
| import com.ruoyi.common.utils.spring.SpringUtils; | ||||
| import com.ruoyi.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<Object[]> methodParams = getMethodParams(invokeTarget); | ||||
|  | ||||
|         if (!isValidClassName(beanName)) | ||||
|         { | ||||
|             Object bean = SpringUtils.getBean(beanName); | ||||
|             invokeMethod(bean, methodName, methodParams); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             Object bean = Class.forName(beanName).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().getDeclaredMethod(methodName, getMethodParamsType(methodParams)); | ||||
|             method.invoke(bean, getMethodParamsValue(methodParams)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             Method method = bean.getClass().getDeclaredMethod(methodName); | ||||
|             method.invoke(bean); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验是否为为class包名 | ||||
|      *  | ||||
|      * @param str 名称 | ||||
|      * @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.contains(str, "'")) | ||||
|             { | ||||
|                 classs.add(new Object[] { StringUtils.replace(str, "'", ""), String.class }); | ||||
|             } | ||||
|             // boolean布尔类型,等于true或者false | ||||
|             else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) | ||||
|             { | ||||
|                 classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); | ||||
|             } | ||||
|             // long长整形,包含L | ||||
|             else if (StringUtils.containsIgnoreCase(str, "L")) | ||||
|             { | ||||
|                 classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class }); | ||||
|             } | ||||
|             // double浮点类型,包含D | ||||
|             else if (StringUtils.containsIgnoreCase(str, "D")) | ||||
|             { | ||||
|                 classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), 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; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,21 @@ | ||||
| package com.ruoyi.quartz.util; | ||||
|  | ||||
| import org.quartz.DisallowConcurrentExecution; | ||||
| import org.quartz.JobExecutionContext; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
|  | ||||
| /** | ||||
|  * 定时任务处理(禁止并发执行) | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  * | ||||
|  */ | ||||
| @DisallowConcurrentExecution | ||||
| public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob | ||||
| { | ||||
|     @Override | ||||
|     protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception | ||||
|     { | ||||
|         JobInvokeUtil.invokeMethod(sysJob); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| package com.ruoyi.quartz.util; | ||||
|  | ||||
| import org.quartz.JobExecutionContext; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
|  | ||||
| /** | ||||
|  * 定时任务处理(允许并发执行) | ||||
|  *  | ||||
|  * @author ruoyi | ||||
|  * | ||||
|  */ | ||||
| public class QuartzJobExecution extends AbstractQuartzJob | ||||
| { | ||||
|     @Override | ||||
|     protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception | ||||
|     { | ||||
|         JobInvokeUtil.invokeMethod(sysJob); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,113 @@ | ||||
| package com.ruoyi.quartz.util; | ||||
|  | ||||
| import org.quartz.CronScheduleBuilder; | ||||
| import org.quartz.CronTrigger; | ||||
| import org.quartz.Job; | ||||
| import org.quartz.JobBuilder; | ||||
| import org.quartz.JobDetail; | ||||
| import org.quartz.JobKey; | ||||
| import org.quartz.Scheduler; | ||||
| import org.quartz.SchedulerException; | ||||
| import org.quartz.TriggerBuilder; | ||||
| import org.quartz.TriggerKey; | ||||
| import com.ruoyi.common.constant.ScheduleConstants; | ||||
| import com.ruoyi.common.exception.job.TaskException; | ||||
| import com.ruoyi.common.exception.job.TaskException.Code; | ||||
| import com.ruoyi.quartz.domain.SysJob; | ||||
|  | ||||
| /** | ||||
|  * 定时任务工具类 | ||||
|  *  | ||||
|  * @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); | ||||
|  | ||||
|         // 按新的cronExpression表达式构建一个新的trigger | ||||
|         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)); | ||||
|         } | ||||
|  | ||||
|         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", Code.CONFIG_ERROR); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user