定时任务支持并发控制
This commit is contained in:
parent
9fc42511c6
commit
e34b4ea63d
@ -22,7 +22,7 @@ public class Global
|
|||||||
/**
|
/**
|
||||||
* 当前对象实例
|
* 当前对象实例
|
||||||
*/
|
*/
|
||||||
private static Global global = null;
|
private static Global global;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存全局属性值
|
* 保存全局属性值
|
||||||
@ -34,18 +34,13 @@ public class Global
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 静态工厂方法 获取当前对象实例 多线程安全单例模式(使用双重同步锁)
|
* 静态工厂方法
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static synchronized Global getInstance()
|
public static synchronized Global getInstance()
|
||||||
{
|
{
|
||||||
if (global == null)
|
if (global == null)
|
||||||
{
|
{
|
||||||
synchronized (Global.class)
|
global = new Global();
|
||||||
{
|
|
||||||
if (global == null)
|
|
||||||
global = new Global();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,10 @@ package com.ruoyi.common.constant;
|
|||||||
*/
|
*/
|
||||||
public interface ScheduleConstants
|
public interface ScheduleConstants
|
||||||
{
|
{
|
||||||
public static final String TASK_CLASS_NAME = "__TASK_CLASS_NAME__";
|
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
|
||||||
|
|
||||||
public static final String TASK_PROPERTIES = "__TASK_PROPERTIES__";
|
/** 执行目标key */
|
||||||
|
public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
|
||||||
|
|
||||||
/** 默认 */
|
/** 默认 */
|
||||||
public static final String MISFIRE_DEFAULT = "0";
|
public static final String MISFIRE_DEFAULT = "0";
|
||||||
|
@ -223,6 +223,7 @@ public class JSONObject extends LinkedHashMap<String, Object>
|
|||||||
{
|
{
|
||||||
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Object>()
|
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Object>()
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
public Object callback(JSONArray arr, int index)
|
public Object callback(JSONArray arr, int index)
|
||||||
{
|
{
|
||||||
return elementAt(arr, index);
|
return elementAt(arr, index);
|
||||||
@ -257,6 +258,7 @@ public class JSONObject extends LinkedHashMap<String, Object>
|
|||||||
{
|
{
|
||||||
endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Void>()
|
endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Void>()
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
public Void callback(JSONArray arr, int index)
|
public Void callback(JSONArray arr, int index)
|
||||||
{
|
{
|
||||||
elementAt(arr, index, value);
|
elementAt(arr, index, value);
|
||||||
@ -285,6 +287,7 @@ public class JSONObject extends LinkedHashMap<String, Object>
|
|||||||
{
|
{
|
||||||
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<JSONObject>()
|
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<JSONObject>()
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
public JSONObject callback(JSONArray arr, int index)
|
public JSONObject callback(JSONArray arr, int index)
|
||||||
{
|
{
|
||||||
return objAt(arr, index);
|
return objAt(arr, index);
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误信息处理类。
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class ExceptionUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取exception的详细错误信息。
|
||||||
|
*/
|
||||||
|
public static String getExceptionMessage(Throwable e)
|
||||||
|
{
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(sw, true));
|
||||||
|
String str = sw.toString();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRootErrorMseeage(Exception e)
|
||||||
|
{
|
||||||
|
Throwable root = ExceptionUtils.getRootCause(e);
|
||||||
|
root = (root == null ? e : root);
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String msg = root.getMessage();
|
||||||
|
if (msg == null)
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return StringUtils.defaultString(msg);
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ public class YamlUtil
|
|||||||
if (map != null && !map.isEmpty() && qualifiedKey != null)
|
if (map != null && !map.isEmpty() && qualifiedKey != null)
|
||||||
{
|
{
|
||||||
String input = String.valueOf(qualifiedKey);
|
String input = String.valueOf(qualifiedKey);
|
||||||
if (!input.equals(""))
|
if (!"".equals(input))
|
||||||
{
|
{
|
||||||
if (input.contains("."))
|
if (input.contains("."))
|
||||||
{
|
{
|
||||||
|
@ -647,7 +647,9 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
tempClass = tempClass.getSuperclass();
|
tempClass = tempClass.getSuperclass();
|
||||||
if (tempClass != null)
|
if (tempClass != null)
|
||||||
|
{
|
||||||
tempFields.addAll(Arrays.asList(tempClass.getDeclaredFields()));
|
tempFields.addAll(Arrays.asList(tempClass.getDeclaredFields()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
putToFields(tempFields);
|
putToFields(tempFields);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.ruoyi.quartz.controller;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
@ -15,6 +16,7 @@ import com.ruoyi.common.core.controller.BaseController;
|
|||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.exception.job.TaskException;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
import com.ruoyi.quartz.domain.SysJob;
|
||||||
import com.ruoyi.quartz.service.ISysJobService;
|
import com.ruoyi.quartz.service.ISysJobService;
|
||||||
@ -65,18 +67,10 @@ public class SysJobController extends BaseController
|
|||||||
@RequiresPermissions("monitor:job:remove")
|
@RequiresPermissions("monitor:job:remove")
|
||||||
@PostMapping("/remove")
|
@PostMapping("/remove")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids) throws SchedulerException
|
||||||
{
|
{
|
||||||
try
|
jobService.deleteJobByIds(ids);
|
||||||
{
|
return success();
|
||||||
jobService.deleteJobByIds(ids);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
return error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("monitor:job:detail")
|
@RequiresPermissions("monitor:job:detail")
|
||||||
@ -90,14 +84,12 @@ public class SysJobController extends BaseController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务调度状态修改
|
* 任务调度状态修改
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
||||||
@RequiresPermissions("monitor:job:changeStatus")
|
@RequiresPermissions("monitor:job:changeStatus")
|
||||||
@PostMapping("/changeStatus")
|
@PostMapping("/changeStatus")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult changeStatus(SysJob job)
|
public AjaxResult changeStatus(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
return toAjax(jobService.changeStatus(job));
|
return toAjax(jobService.changeStatus(job));
|
||||||
}
|
}
|
||||||
@ -109,9 +101,10 @@ public class SysJobController extends BaseController
|
|||||||
@RequiresPermissions("monitor:job:changeStatus")
|
@RequiresPermissions("monitor:job:changeStatus")
|
||||||
@PostMapping("/run")
|
@PostMapping("/run")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult run(SysJob job)
|
public AjaxResult run(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
return toAjax(jobService.run(job));
|
jobService.run(job);
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,7 +118,6 @@ public class SysJobController extends BaseController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增保存调度
|
* 新增保存调度
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Log(title = "定时任务", businessType = BusinessType.INSERT)
|
@Log(title = "定时任务", businessType = BusinessType.INSERT)
|
||||||
@RequiresPermissions("monitor:job:add")
|
@RequiresPermissions("monitor:job:add")
|
||||||
@ -148,13 +140,12 @@ public class SysJobController extends BaseController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改保存调度
|
* 修改保存调度
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
||||||
@RequiresPermissions("monitor:job:edit")
|
@RequiresPermissions("monitor:job:edit")
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysJob job ) throws Exception
|
public AjaxResult editSave(SysJob job) throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
return toAjax(jobService.updateJobCron(job));
|
return toAjax(jobService.updateJobCron(job));
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ public class SysJob extends BaseEntity implements Serializable
|
|||||||
@Excel(name = "计划策略 ")
|
@Excel(name = "计划策略 ")
|
||||||
private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
|
private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
|
||||||
|
|
||||||
|
/** 是否并发执行(0允许 1禁止) */
|
||||||
|
private String concurrent;
|
||||||
|
|
||||||
/** 任务状态(0正常 1暂停) */
|
/** 任务状态(0正常 1暂停) */
|
||||||
@Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停")
|
@Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停")
|
||||||
private String status;
|
private String status;
|
||||||
@ -130,6 +133,16 @@ public class SysJob extends BaseEntity implements Serializable
|
|||||||
this.misfirePolicy = misfirePolicy;
|
this.misfirePolicy = misfirePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getConcurrent()
|
||||||
|
{
|
||||||
|
return concurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConcurrent(String concurrent)
|
||||||
|
{
|
||||||
|
this.concurrent = concurrent;
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatus()
|
public String getStatus()
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
@ -139,7 +152,7 @@ public class SysJob extends BaseEntity implements Serializable
|
|||||||
{
|
{
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
@ -151,6 +164,7 @@ public class SysJob extends BaseEntity implements Serializable
|
|||||||
.append("cronExpression", getCronExpression())
|
.append("cronExpression", getCronExpression())
|
||||||
.append("nextValidTime", getNextValidTime())
|
.append("nextValidTime", getNextValidTime())
|
||||||
.append("misfirePolicy", getMisfirePolicy())
|
.append("misfirePolicy", getMisfirePolicy())
|
||||||
|
.append("concurrent", getConcurrent())
|
||||||
.append("status", getStatus())
|
.append("status", getStatus())
|
||||||
.append("createBy", getCreateBy())
|
.append("createBy", getCreateBy())
|
||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
@ -159,4 +173,4 @@ public class SysJob extends BaseEntity implements Serializable
|
|||||||
.append("remark", getRemark())
|
.append("remark", getRemark())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package com.ruoyi.quartz.domain;
|
package com.ruoyi.quartz.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
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;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
@ -46,6 +48,14 @@ public class SysJobLog extends BaseEntity
|
|||||||
@Excel(name = "异常信息")
|
@Excel(name = "异常信息")
|
||||||
private String exceptionInfo;
|
private String exceptionInfo;
|
||||||
|
|
||||||
|
/** 开始时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date startTime;
|
||||||
|
|
||||||
|
/** 结束时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
public Long getJobLogId()
|
public Long getJobLogId()
|
||||||
{
|
{
|
||||||
return jobLogId;
|
return jobLogId;
|
||||||
@ -125,6 +135,26 @@ public class SysJobLog extends BaseEntity
|
|||||||
{
|
{
|
||||||
this.exceptionInfo = exceptionInfo;
|
this.exceptionInfo = exceptionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(Date startTime)
|
||||||
|
{
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getEndTime()
|
||||||
|
{
|
||||||
|
return endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndTime(Date endTime)
|
||||||
|
{
|
||||||
|
this.endTime = endTime;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -137,7 +167,8 @@ public class SysJobLog extends BaseEntity
|
|||||||
.append("jobMessage", getJobMessage())
|
.append("jobMessage", getJobMessage())
|
||||||
.append("status", getStatus())
|
.append("status", getStatus())
|
||||||
.append("exceptionInfo", getExceptionInfo())
|
.append("exceptionInfo", getExceptionInfo())
|
||||||
.append("createTime", getCreateTime())
|
.append("startTime", getStartTime())
|
||||||
|
.append("endTime", getEndTime())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.ruoyi.quartz.service;
|
package com.ruoyi.quartz.service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
|
import com.ruoyi.common.exception.job.TaskException;
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
import com.ruoyi.quartz.domain.SysJob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +34,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int pauseJob(SysJob job);
|
public int pauseJob(SysJob job) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复任务
|
* 恢复任务
|
||||||
@ -40,7 +42,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int resumeJob(SysJob job);
|
public int resumeJob(SysJob job) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除任务后,所对应的trigger也将被删除
|
* 删除任务后,所对应的trigger也将被删除
|
||||||
@ -48,7 +50,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteJob(SysJob job);
|
public int deleteJob(SysJob job) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除调度信息
|
* 批量删除调度信息
|
||||||
@ -56,7 +58,7 @@ public interface ISysJobService
|
|||||||
* @param ids 需要删除的数据ID
|
* @param ids 需要删除的数据ID
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public void deleteJobByIds(String ids);
|
public void deleteJobByIds(String ids) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务调度状态修改
|
* 任务调度状态修改
|
||||||
@ -64,7 +66,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int changeStatus(SysJob job);
|
public int changeStatus(SysJob job) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即运行任务
|
* 立即运行任务
|
||||||
@ -72,7 +74,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int run(SysJob job);
|
public void run(SysJob job) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增任务表达式
|
* 新增任务表达式
|
||||||
@ -80,7 +82,7 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int insertJobCron(SysJob job);
|
public int insertJobCron(SysJob job) throws SchedulerException, TaskException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新任务的时间表达式
|
* 更新任务的时间表达式
|
||||||
@ -88,8 +90,8 @@ public interface ISysJobService
|
|||||||
* @param job 调度信息
|
* @param job 调度信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int updateJobCron(SysJob job);
|
public int updateJobCron(SysJob job) throws SchedulerException, TaskException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验cron表达式是否有效
|
* 校验cron表达式是否有效
|
||||||
*
|
*
|
||||||
|
@ -4,11 +4,13 @@ import java.util.List;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import org.quartz.CronTrigger;
|
import org.quartz.CronTrigger;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import com.ruoyi.common.constant.ScheduleConstants;
|
import com.ruoyi.common.constant.ScheduleConstants;
|
||||||
import com.ruoyi.common.core.text.Convert;
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.common.exception.job.TaskException;
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
import com.ruoyi.quartz.domain.SysJob;
|
||||||
import com.ruoyi.quartz.mapper.SysJobMapper;
|
import com.ruoyi.quartz.mapper.SysJobMapper;
|
||||||
import com.ruoyi.quartz.service.ISysJobService;
|
import com.ruoyi.quartz.service.ISysJobService;
|
||||||
@ -33,7 +35,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
* 项目启动时,初始化定时器
|
* 项目启动时,初始化定时器
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init()
|
public void init() throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
List<SysJob> jobList = jobMapper.selectJobAll();
|
List<SysJob> jobList = jobMapper.selectJobAll();
|
||||||
for (SysJob job : jobList)
|
for (SysJob job : jobList)
|
||||||
@ -82,7 +84,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int pauseJob(SysJob job)
|
public int pauseJob(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
||||||
int rows = jobMapper.updateJob(job);
|
int rows = jobMapper.updateJob(job);
|
||||||
@ -100,7 +102,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int resumeJob(SysJob job)
|
public int resumeJob(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
|
job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
|
||||||
int rows = jobMapper.updateJob(job);
|
int rows = jobMapper.updateJob(job);
|
||||||
@ -118,7 +120,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int deleteJob(SysJob job)
|
public int deleteJob(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
int rows = jobMapper.deleteJobById(job.getJobId());
|
int rows = jobMapper.deleteJobById(job.getJobId());
|
||||||
if (rows > 0)
|
if (rows > 0)
|
||||||
@ -136,7 +138,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteJobByIds(String ids)
|
public void deleteJobByIds(String ids) throws SchedulerException
|
||||||
{
|
{
|
||||||
Long[] jobIds = Convert.toLongArray(ids);
|
Long[] jobIds = Convert.toLongArray(ids);
|
||||||
for (Long jobId : jobIds)
|
for (Long jobId : jobIds)
|
||||||
@ -153,7 +155,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int changeStatus(SysJob job)
|
public int changeStatus(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
int rows = 0;
|
int rows = 0;
|
||||||
String status = job.getStatus();
|
String status = job.getStatus();
|
||||||
@ -175,9 +177,9 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int run(SysJob job)
|
public void run(SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
return ScheduleUtils.run(scheduler, selectJobById(job.getJobId()));
|
ScheduleUtils.run(scheduler, selectJobById(job.getJobId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,7 +189,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int insertJobCron(SysJob job)
|
public int insertJobCron(SysJob job) throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
||||||
int rows = jobMapper.insertJob(job);
|
int rows = jobMapper.insertJob(job);
|
||||||
@ -205,7 +207,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int updateJobCron(SysJob job)
|
public int updateJobCron(SysJob job) throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
int rows = jobMapper.updateJob(job);
|
int rows = jobMapper.updateJob(job);
|
||||||
if (rows > 0)
|
if (rows > 0)
|
||||||
@ -214,7 +216,7 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
}
|
}
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验cron表达式是否有效
|
* 校验cron表达式是否有效
|
||||||
*
|
*
|
||||||
@ -225,5 +227,5 @@ public class SysJobServiceImpl implements ISysJobService
|
|||||||
public boolean checkCronExpressionIsValid(String cronExpression)
|
public boolean checkCronExpressionIsValid(String cronExpression)
|
||||||
{
|
{
|
||||||
return CronUtils.isValid(cronExpression);
|
return CronUtils.isValid(cronExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
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.setMethodName(sysJob.getMethodName());
|
||||||
|
sysJobLog.setMethodParams(sysJob.getMethodParams());
|
||||||
|
sysJobLog.setStartTime(startTime);
|
||||||
|
sysJobLog.setEndTime(new Date());
|
||||||
|
long runMs = sysJobLog.getEndTime().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,57 @@
|
|||||||
|
package com.ruoyi.quartz.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Object bean = SpringUtils.getBean(sysJob.getJobName());
|
||||||
|
String methodName = sysJob.getMethodName();
|
||||||
|
String methodParams = sysJob.getMethodParams();
|
||||||
|
|
||||||
|
invokeSpringBean(bean, methodName, methodParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用任务方法
|
||||||
|
*
|
||||||
|
* @param bean 目标对象
|
||||||
|
* @param methodName 方法名称
|
||||||
|
* @param methodParams 方法参数
|
||||||
|
* @throws InvocationTargetException
|
||||||
|
* @throws SecurityException
|
||||||
|
* @throws NoSuchMethodException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private static void invokeSpringBean(Object bean, String methodName, String methodParams)
|
||||||
|
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
|
||||||
|
InvocationTargetException
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotEmpty(methodParams))
|
||||||
|
{
|
||||||
|
Method method = bean.getClass().getDeclaredMethod(methodName, String.class);
|
||||||
|
method.invoke(bean, methodParams);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Method method = bean.getClass().getDeclaredMethod(methodName);
|
||||||
|
method.invoke(bean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,80 +0,0 @@
|
|||||||
package com.ruoyi.quartz.util;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import org.quartz.DisallowConcurrentExecution;
|
|
||||||
import org.quartz.JobExecutionContext;
|
|
||||||
import org.quartz.JobExecutionException;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.constant.ScheduleConstants;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时任务处理
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@DisallowConcurrentExecution
|
|
||||||
public class ScheduleJob extends QuartzJobBean
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class);
|
|
||||||
|
|
||||||
private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor");
|
|
||||||
|
|
||||||
private final static ISysJobLogService jobLogService = SpringUtils.getBean(ISysJobLogService.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
|
|
||||||
{
|
|
||||||
SysJob job = new SysJob();
|
|
||||||
BeanUtils.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
|
|
||||||
|
|
||||||
SysJobLog jobLog = new SysJobLog();
|
|
||||||
jobLog.setJobName(job.getJobName());
|
|
||||||
jobLog.setJobGroup(job.getJobGroup());
|
|
||||||
jobLog.setMethodName(job.getMethodName());
|
|
||||||
jobLog.setMethodParams(job.getMethodParams());
|
|
||||||
jobLog.setCreateTime(new Date());
|
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 执行任务
|
|
||||||
log.info("任务开始执行 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
|
|
||||||
ScheduleRunnable task = new ScheduleRunnable(job.getJobName(), job.getMethodName(), job.getMethodParams());
|
|
||||||
Future<?> future = executor.submit(task);
|
|
||||||
future.get();
|
|
||||||
long times = System.currentTimeMillis() - startTime;
|
|
||||||
// 任务状态 0:成功 1:失败
|
|
||||||
jobLog.setStatus(Constants.SUCCESS);
|
|
||||||
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
|
|
||||||
|
|
||||||
log.info("任务执行结束 - 名称:{} 耗时:{} 毫秒", job.getJobName(), times);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.info("任务执行失败 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
|
|
||||||
log.error("任务执行异常 - :", e);
|
|
||||||
long times = System.currentTimeMillis() - startTime;
|
|
||||||
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
|
|
||||||
// 任务状态 0:成功 1:失败
|
|
||||||
jobLog.setStatus(Constants.FAIL);
|
|
||||||
jobLog.setExceptionInfo(StringUtils.substring(e.getMessage(), 0, 2000));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
jobLogService.addJobLog(jobLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package com.ruoyi.quartz.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import com.ruoyi.common.exception.BusinessException;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行定时任务
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ScheduleRunnable implements Runnable
|
|
||||||
{
|
|
||||||
private Object target;
|
|
||||||
private Method method;
|
|
||||||
private String params;
|
|
||||||
|
|
||||||
public ScheduleRunnable(String beanName, String methodName, String params)
|
|
||||||
throws NoSuchMethodException, SecurityException
|
|
||||||
{
|
|
||||||
this.target = SpringUtils.getBean(beanName);
|
|
||||||
this.params = params;
|
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(params))
|
|
||||||
{
|
|
||||||
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.method = target.getClass().getDeclaredMethod(methodName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ReflectionUtils.makeAccessible(method);
|
|
||||||
if (StringUtils.isNotEmpty(params))
|
|
||||||
{
|
|
||||||
method.invoke(target, params);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
method.invoke(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new BusinessException("执行定时任务失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package com.ruoyi.quartz.util;
|
|||||||
|
|
||||||
import org.quartz.CronScheduleBuilder;
|
import org.quartz.CronScheduleBuilder;
|
||||||
import org.quartz.CronTrigger;
|
import org.quartz.CronTrigger;
|
||||||
|
import org.quartz.Job;
|
||||||
import org.quartz.JobBuilder;
|
import org.quartz.JobBuilder;
|
||||||
import org.quartz.JobDataMap;
|
import org.quartz.JobDataMap;
|
||||||
import org.quartz.JobDetail;
|
import org.quartz.JobDetail;
|
||||||
@ -27,6 +28,18 @@ public class ScheduleUtils
|
|||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
|
private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到quartz任务类
|
||||||
|
*
|
||||||
|
* @param sysJob 执行计划
|
||||||
|
* @return 具体执行任务类
|
||||||
|
*/
|
||||||
|
private static Class<? extends Job> getQuartzJobClass(SysJob sysJob)
|
||||||
|
{
|
||||||
|
boolean isConcurrent = "0".equals(sysJob.getConcurrent());
|
||||||
|
return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取触发器key
|
* 获取触发器key
|
||||||
*/
|
*/
|
||||||
@ -62,147 +75,89 @@ public class ScheduleUtils
|
|||||||
/**
|
/**
|
||||||
* 创建定时任务
|
* 创建定时任务
|
||||||
*/
|
*/
|
||||||
public static void createScheduleJob(Scheduler scheduler, SysJob job)
|
public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
try
|
Class<? extends Job> jobClass = getQuartzJobClass(job);
|
||||||
|
// 构建job信息
|
||||||
|
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(job.getJobId())).build();
|
||||||
|
|
||||||
|
// 表达式调度构建器
|
||||||
|
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
|
||||||
|
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
|
||||||
|
|
||||||
|
// 按新的cronExpression表达式构建一个新的trigger
|
||||||
|
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId()))
|
||||||
|
.withSchedule(cronScheduleBuilder).build();
|
||||||
|
|
||||||
|
// 放入参数,运行时的方法可以获取
|
||||||
|
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
|
||||||
|
|
||||||
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
|
||||||
|
// 暂停任务
|
||||||
|
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
|
||||||
{
|
{
|
||||||
// 构建job信息
|
pauseJob(scheduler, job.getJobId());
|
||||||
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build();
|
|
||||||
|
|
||||||
// 表达式调度构建器
|
|
||||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
|
|
||||||
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
|
|
||||||
|
|
||||||
// 按新的cronExpression表达式构建一个新的trigger
|
|
||||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId()))
|
|
||||||
.withSchedule(cronScheduleBuilder).build();
|
|
||||||
|
|
||||||
// 放入参数,运行时的方法可以获取
|
|
||||||
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
|
|
||||||
|
|
||||||
scheduler.scheduleJob(jobDetail, trigger);
|
|
||||||
|
|
||||||
// 暂停任务
|
|
||||||
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
|
|
||||||
{
|
|
||||||
pauseJob(scheduler, job.getJobId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SchedulerException e)
|
|
||||||
{
|
|
||||||
log.error("createScheduleJob 异常:", e);
|
|
||||||
}
|
|
||||||
catch (TaskException e)
|
|
||||||
{
|
|
||||||
log.error("createScheduleJob 异常:", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新定时任务
|
* 更新定时任务
|
||||||
*/
|
*/
|
||||||
public static void updateScheduleJob(Scheduler scheduler, SysJob job)
|
public static void updateScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
|
||||||
{
|
{
|
||||||
try
|
JobKey jobKey = getJobKey(job.getJobId());
|
||||||
|
|
||||||
|
// 判断是否存在
|
||||||
|
if (scheduler.checkExists(jobKey))
|
||||||
{
|
{
|
||||||
TriggerKey triggerKey = getTriggerKey(job.getJobId());
|
// 先移除,然后做更新操作
|
||||||
|
scheduler.deleteJob(jobKey);
|
||||||
// 表达式调度构建器
|
|
||||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
|
|
||||||
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
|
|
||||||
|
|
||||||
CronTrigger trigger = getCronTrigger(scheduler, job.getJobId());
|
|
||||||
|
|
||||||
// 按新的cronExpression表达式重新构建trigger
|
|
||||||
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
|
||||||
|
|
||||||
// 参数
|
|
||||||
trigger.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
|
|
||||||
|
|
||||||
scheduler.rescheduleJob(triggerKey, trigger);
|
|
||||||
|
|
||||||
// 暂停任务
|
|
||||||
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
|
|
||||||
{
|
|
||||||
pauseJob(scheduler, job.getJobId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (SchedulerException e)
|
|
||||||
|
createScheduleJob(scheduler, job);
|
||||||
|
|
||||||
|
// 暂停任务
|
||||||
|
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
|
||||||
{
|
{
|
||||||
log.error("SchedulerException 异常:", e);
|
pauseJob(scheduler, job.getJobId());
|
||||||
}
|
|
||||||
catch (TaskException e)
|
|
||||||
{
|
|
||||||
log.error("SchedulerException 异常:", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即执行任务
|
* 立即执行任务
|
||||||
*/
|
*/
|
||||||
public static int run(Scheduler scheduler, SysJob job)
|
public static void run(Scheduler scheduler, SysJob job) throws SchedulerException
|
||||||
{
|
{
|
||||||
int rows = 0;
|
// 参数
|
||||||
try
|
JobDataMap dataMap = new JobDataMap();
|
||||||
{
|
dataMap.put(ScheduleConstants.TASK_PROPERTIES, job);
|
||||||
// 参数
|
|
||||||
JobDataMap dataMap = new JobDataMap();
|
|
||||||
dataMap.put(ScheduleConstants.TASK_PROPERTIES, job);
|
|
||||||
|
|
||||||
scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
|
scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
|
||||||
rows = 1;
|
|
||||||
}
|
|
||||||
catch (SchedulerException e)
|
|
||||||
{
|
|
||||||
log.error("run 异常:", e);
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂停任务
|
* 暂停任务
|
||||||
*/
|
*/
|
||||||
public static void pauseJob(Scheduler scheduler, Long jobId)
|
public static void pauseJob(Scheduler scheduler, Long jobId) throws SchedulerException
|
||||||
{
|
{
|
||||||
try
|
scheduler.pauseJob(getJobKey(jobId));
|
||||||
{
|
|
||||||
scheduler.pauseJob(getJobKey(jobId));
|
|
||||||
}
|
|
||||||
catch (SchedulerException e)
|
|
||||||
{
|
|
||||||
log.error("pauseJob 异常:", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复任务
|
* 恢复任务
|
||||||
*/
|
*/
|
||||||
public static void resumeJob(Scheduler scheduler, Long jobId)
|
public static void resumeJob(Scheduler scheduler, Long jobId) throws SchedulerException
|
||||||
{
|
{
|
||||||
try
|
scheduler.resumeJob(getJobKey(jobId));
|
||||||
{
|
|
||||||
scheduler.resumeJob(getJobKey(jobId));
|
|
||||||
}
|
|
||||||
catch (SchedulerException e)
|
|
||||||
{
|
|
||||||
log.error("resumeJob 异常:", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除定时任务
|
* 删除定时任务
|
||||||
*/
|
*/
|
||||||
public static void deleteScheduleJob(Scheduler scheduler, Long jobId)
|
public static void deleteScheduleJob(Scheduler scheduler, Long jobId) throws SchedulerException
|
||||||
{
|
{
|
||||||
try
|
scheduler.deleteJob(getJobKey(jobId));
|
||||||
{
|
|
||||||
scheduler.deleteJob(getJobKey(jobId));
|
|
||||||
}
|
|
||||||
catch (SchedulerException e)
|
|
||||||
{
|
|
||||||
log.error("deleteScheduleJob 异常:", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
|
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
|
||||||
@ -219,7 +174,8 @@ public class ScheduleUtils
|
|||||||
case ScheduleConstants.MISFIRE_DO_NOTHING:
|
case ScheduleConstants.MISFIRE_DO_NOTHING:
|
||||||
return cb.withMisfireHandlingInstructionDoNothing();
|
return cb.withMisfireHandlingInstructionDoNothing();
|
||||||
default:
|
default:
|
||||||
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
|
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
|
||||||
|
+ "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="methodParams" column="method_params" />
|
<result property="methodParams" column="method_params" />
|
||||||
<result property="cronExpression" column="cron_expression" />
|
<result property="cronExpression" column="cron_expression" />
|
||||||
<result property="misfirePolicy" column="misfire_policy" />
|
<result property="misfirePolicy" column="misfire_policy" />
|
||||||
|
<result property="concurrent" column="concurrent" />
|
||||||
<result property="status" column="status" />
|
<result property="status" column="status" />
|
||||||
<result property="createBy" column="create_by" />
|
<result property="createBy" column="create_by" />
|
||||||
<result property="createTime" column="create_time" />
|
<result property="createTime" column="create_time" />
|
||||||
@ -21,7 +22,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectJobVo">
|
<sql id="selectJobVo">
|
||||||
select job_id, job_name, job_group, method_name, method_params, cron_expression, misfire_policy, status, create_by, create_time, remark
|
select job_id, job_name, job_group, method_name, method_params, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark
|
||||||
from sys_job
|
from sys_job
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="methodParams != null">method_params = #{methodParams},</if>
|
<if test="methodParams != null">method_params = #{methodParams},</if>
|
||||||
<if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
|
<if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
|
||||||
<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
|
<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
|
||||||
|
<if test="concurrent != null and concurrent != ''">concurrent = #{concurrent},</if>
|
||||||
<if test="status !=null">status = #{status},</if>
|
<if test="status !=null">status = #{status},</if>
|
||||||
<if test="remark != null and remark != ''">remark = #{remark},</if>
|
<if test="remark != null and remark != ''">remark = #{remark},</if>
|
||||||
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
||||||
@ -86,6 +88,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="methodParams != null and methodParams != ''">method_params,</if>
|
<if test="methodParams != null and methodParams != ''">method_params,</if>
|
||||||
<if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
|
<if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
|
||||||
<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
|
<if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
|
||||||
|
<if test="concurrent != null and concurrent != ''">concurrent,</if>
|
||||||
<if test="status != null and status != ''">status,</if>
|
<if test="status != null and status != ''">status,</if>
|
||||||
<if test="remark != null and remark != ''">remark,</if>
|
<if test="remark != null and remark != ''">remark,</if>
|
||||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||||
@ -98,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="methodParams != null and methodParams != ''">#{methodParams},</if>
|
<if test="methodParams != null and methodParams != ''">#{methodParams},</if>
|
||||||
<if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
|
<if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
|
||||||
<if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
|
<if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
|
||||||
|
<if test="concurrent != null and concurrent != ''">#{concurrent},</if>
|
||||||
<if test="status != null and status != ''">#{status},</if>
|
<if test="status != null and status != ''">#{status},</if>
|
||||||
<if test="remark != null and remark != ''">#{remark},</if>
|
<if test="remark != null and remark != ''">#{remark},</if>
|
||||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||||
|
@ -43,6 +43,13 @@
|
|||||||
<label class="radio-box"> <input type="radio" name="misfirePolicy" value="3" /> 放弃执行 </label>
|
<label class="radio-box"> <input type="radio" name="misfirePolicy" value="3" /> 放弃执行 </label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-3 control-label">并发执行:</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<label class="radio-box"> <input type="radio" name="concurrent" value="0"/> 允许 </label>
|
||||||
|
<label class="radio-box"> <input type="radio" name="concurrent" value="1" th:checked="true"/> 禁止 </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">状态:</label>
|
<label class="col-sm-3 control-label">状态:</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
@ -82,6 +82,11 @@
|
|||||||
<div class="form-control-static" th:if="${job.misfirePolicy == '2'}">执行一次</div>
|
<div class="form-control-static" th:if="${job.misfirePolicy == '2'}">执行一次</div>
|
||||||
<div class="form-control-static" th:if="${job.misfirePolicy == '3'}">放弃执行</div>
|
<div class="form-control-static" th:if="${job.misfirePolicy == '3'}">放弃执行</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-3 control-label">并发执行:</label>
|
||||||
|
<div class="form-control-static" th:class="${job.concurrent == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${job.concurrent == '0' ? '允许' : '禁止'}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">执行状态:</label>
|
<label class="col-sm-3 control-label">执行状态:</label>
|
||||||
<div class="form-control-static" th:class="${job.status == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${job.status == '0' ? '正常' : '暂停'}">
|
<div class="form-control-static" th:class="${job.status == '0' ? 'label label-primary' : 'label label-danger'}" th:text="${job.status == '0' ? '正常' : '暂停'}">
|
||||||
|
@ -44,6 +44,13 @@
|
|||||||
<label class="radio-box"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="3" /> 放弃执行 </label>
|
<label class="radio-box"> <input type="radio" th:field="*{misfirePolicy}" name="misfirePolicy" value="3" /> 放弃执行 </label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-3 control-label">并发执行:</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<label class="radio-box"> <input type="radio" th:field="*{concurrent}" name="concurrent" value="0"/> 允许 </label>
|
||||||
|
<label class="radio-box"> <input type="radio" th:field="*{concurrent}" name="concurrent" value="1"/> 禁止 </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">状态:</label>
|
<label class="col-sm-3 control-label">状态:</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
@ -122,7 +122,7 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
formatter: function(value, row, index) {
|
formatter: function(value, row, index) {
|
||||||
var actions = [];
|
var actions = [];
|
||||||
actions.push('<a class="btn btn-primary btn-xs ' + statusFlag + '" href="#" onclick="run(\'' + row.jobId + '\')"><i class="fa fa-play-circle-o"></i> 执行</a> ');
|
actions.push('<a class="btn btn-primary btn-xs ' + statusFlag + '" href="#" onclick="run(\'' + row.jobId + '\')"><i class="fa fa-play-circle-o"></i> 执行一次</a> ');
|
||||||
actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="#" onclick="$.operate.detail(\'' + row.jobId + '\')"><i class="fa fa-search"></i>详细</a> ');
|
actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="#" onclick="$.operate.detail(\'' + row.jobId + '\')"><i class="fa fa-search"></i>详细</a> ');
|
||||||
return actions.join('');
|
return actions.join('');
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@
|
|||||||
|
|
||||||
/* 立即执行一次 */
|
/* 立即执行一次 */
|
||||||
function run(jobId) {
|
function run(jobId) {
|
||||||
$.modal.confirm("确认要立即执行任务吗?", function() {
|
$.modal.confirm("确认要立即执行一次任务吗?", function() {
|
||||||
$.operate.post(prefix + "/run", { "jobId": jobId});
|
$.operate.post(prefix + "/run", { "jobId": jobId});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -568,6 +568,7 @@ create table sys_job (
|
|||||||
method_params varchar(50) default null comment '方法参数',
|
method_params varchar(50) default null comment '方法参数',
|
||||||
cron_expression varchar(255) default '' comment 'cron执行表达式',
|
cron_expression varchar(255) default '' comment 'cron执行表达式',
|
||||||
misfire_policy varchar(20) default '3' comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
|
misfire_policy varchar(20) default '3' comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
|
||||||
|
concurrent char default '1' comment '是否并发执行(0允许 1禁止)',
|
||||||
status char(1) default '0' comment '状态(0正常 1暂停)',
|
status char(1) default '0' comment '状态(0正常 1暂停)',
|
||||||
create_by varchar(64) default '' comment '创建者',
|
create_by varchar(64) default '' comment '创建者',
|
||||||
create_time datetime comment '创建时间',
|
create_time datetime comment '创建时间',
|
||||||
@ -577,8 +578,8 @@ create table sys_job (
|
|||||||
primary key (job_id, job_name, job_group)
|
primary key (job_id, job_name, job_group)
|
||||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '定时任务调度表';
|
) engine=innodb auto_increment=100 default charset=utf8 comment = '定时任务调度表';
|
||||||
|
|
||||||
insert into sys_job values(1, 'ryTask', '系统默认(无参)', 'ryNoParams', '', '0/10 * * * * ?', '3', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_job values(1, 'ryTask', '系统默认(无参)', 'ryNoParams', '', '0/10 * * * * ?', '3', '1', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_job values(2, 'ryTask', '系统默认(有参)', 'ryParams', 'ry', '0/20 * * * * ?', '3', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_job values(2, 'ryTask', '系统默认(有参)', 'ryParams', 'ry', '0/20 * * * * ?', '3', '1', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
Loading…
x
Reference in New Issue
Block a user