springboot Quartz 实现动态定时任务
springboot Quartz 实现动态定时任务实现上参考ruoyi的quartz一.引言Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。它提供了巨大的灵 活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,EJB作业预构 建,JavaMail及其它,支持cron-like表达式等等。
·
springboot Quartz 实现动态定时任务
实现上参考ruoyi的quartz
一.引言
Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。它提供了巨大的灵 活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,EJB作业预构 建,JavaMail及其它,支持cron-like表达式等等。
该项目已经被 Terracotta收购。
二.实战
1.在springboot 中的maven中导入jar
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
2.配置quartz
package com.nhiot.web.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;
@Configuration
public class QuartzConfiguration
{
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
{
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "nhiotScheduler");
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("nhiotScheduler");
// 延时启动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选,QuartzScheduler
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
// 设置自动启动,默认为true
factory.setAutoStartup(true);
return factory;
}
}
3.创建quartz 需要的表
4.创建任务类
package com.nhiot.entity.quartz;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.nhiot.constants.ScheduleConstants;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* @Description
*
* @Author www
* @Date 2020/5/7 17:13
*
**/
@Data
@Entity
@Table(name = "t_task")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class SysTask implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(columnDefinition = "BigInt(10) COMMENT '主键ID'")
private Long id;
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务名'")
private String jobName;
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务描述'")
private String description;
@Column(columnDefinition = "VARCHAR(255) COMMENT 'cron表达式'")
private String cronExpression;
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务执行时调用哪个类的方法 包名+类名'")
private String beanClass;
@Column(columnDefinition = "VARCHAR(255) COMMENT '计划策略'")
@ApiModelProperty("计划策略-0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行")
private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
/** 是否并发执行(0允许 1禁止) */
@Column(columnDefinition = "VARCHAR(255) COMMENT '并发执行'")
@ApiModelProperty("并发执行-0=允许,1=禁止")
private String concurrent="0";
@Column(columnDefinition = "VARCHAR(255) COMMENT '组织ID'")
@ApiModelProperty("组织Id")
private String organizationId;
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务状态'")
private String jobStatus="0";
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务分组'")
private String jobGroup;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@CreatedDate
@Column(columnDefinition = "DATETIME COMMENT '创建时间'")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@LastModifiedDate
@Column(columnDefinition = "DATETIME COMMENT '修改时间'")
private Date updateTime;
@CreatedBy
@Column(columnDefinition = "VARCHAR(255) COMMENT '创建人'")
private String createBy;
@Column(columnDefinition = "VARCHAR(255) COMMENT '修改人'")
@LastModifiedBy
private String updateBy;
@Version
@ApiModelProperty(value = "版本号")
@Column(columnDefinition = "int(10) COMMENT '版本号'")
private int versionId;
}
定时任务执行日志类
package com.nhiot.entity.quartz;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* 定时任务调度日志表 sys_task_log
*
* @author www
*/
@Data
@Entity
@Table(name = "t_task_log")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class SysTaskLog implements Serializable
{
private static final long serialVersionUID = 1L;
/** ID */
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(columnDefinition = "BigInt(10) COMMENT '主键ID'")
private Long id;
/** 任务名称 */
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务名称'")
private String jobName;
/** 任务组名 */
@Column(columnDefinition = "VARCHAR(255) COMMENT '任务组名'")
private String jobGroup;
/** 调用目标字符串 */
@Column(columnDefinition = "VARCHAR(255) COMMENT '调用目标字符串'")
private String invokeTarget;
/** 日志信息 */
@Column(columnDefinition = "VARCHAR(500) COMMENT '日志信息'")
private String jobMessage;
/** 执行状态(0正常 1失败) */
@Column(columnDefinition = "VARCHAR(20) COMMENT '执行状态(0正常 1失败)'")
private String status;
/** 异常信息 */
@Column(columnDefinition = "VARCHAR(2000) COMMENT '异常信息'")
private String exceptionInfo;
/** 开始时间 */
@Column(columnDefinition = "DATETIME COMMENT '开始时间'")
private Date startTime;
/** 结束时间 */
@Column(columnDefinition = "DATETIME COMMENT '结束时间'")
private Date endTime;
}
5.写controller控制器
@Autowired
private TaskService taskService;
@RequestMapping(value = "/saveOrUpdate",method = RequestMethod.POST)
@ApiOperation("添加/修改定时任务")
public Result<String> saveOrUpdate(@RequestBody TaskAddAndEditRequest request)
{
return taskService.saveOrUpdate(request);
}
@RequestMapping(value = "/detail",method = RequestMethod.GET)
@ApiOperation("查询定时任务详情")
public Result<SysTask> detailTask(String id)
{
return taskService.detailTask(id);
}
@RequestMapping(value = "/delete/ids",method = RequestMethod.DELETE)
@ApiOperation("删除定时任务")
public Result<String> deleteTaskByIds(String ids)
{
try {
return taskService.deleteTaskByIds(ids);
} catch (SchedulerException e) {
e.printStackTrace();
}
return null;
}
/**
* 任务调度立即执行一次
*/
@PostMapping("/run")
@ResponseBody
public Result<String> run(String id) throws SchedulerException
{
taskService.run(id);
return Result.<String>builder().success().build();
}
6.service实现类
@Autowired
private TaskRepository taskRepository;
@Autowired
@Qualifier("schedulerFactoryBean")
private Scheduler scheduler;
/**
* @Method
* @Author www
* @Version 1.0
* @Description 添加/修改定时任务
* @Return
* @Date 2020/8/17 16:58
*/
@Override
public Result<String> saveOrUpdate(TaskAddAndEditRequest request)
{
SysTask sysTask = null;
if(request.getId()==null)
{
sysTask = new SysTask();
}else{
sysTask = taskRepository.getOne(request.getId());
}
BeanUtils.copyPropertiesExcludeNull(request, sysTask);
sysTask.setBeanClass("com.nhiot.service.bengbu.impl.BengbuServiceImpl.uploadAttendance('"+request.getJobGroup()+"')");
sysTask.setConcurrent("0");
sysTask.setCronExpression(CronUtils.resetCronExpression(request.getCronExpression()));
if(!CronUtils.isValid(sysTask.getCronExpression()))
{
sysTask.setCronExpression(request.getCronExpression());
}
SysTask sysTask1 = taskRepository.saveAndFlush(sysTask);
try {
updateSchedulerJob(sysTask1,sysTask1.getJobGroup());
} catch (SchedulerException e) {
e.printStackTrace();
} catch (TaskException e) {
e.printStackTrace();
}
return Result.<String>builder().success().build();
}
/**
* 项目启动时,初始化定时器
主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
*/
@PostConstruct
public void init() throws SchedulerException, TaskException
{
scheduler.clear();
List<SysTask> taskList = taskRepository.findAll();
for (SysTask sysTask : taskList)
{
System.out.println(sysTask.getJobName());
ScheduleUtils.createScheduleJob(scheduler, sysTask);
}
}
/**
* @Method
* @Author www
* @Version 1.0
* @Description 查询定时任务详情
* @Return
* @Date 2020/8/17 17:23
*/
@Override
public Result<SysTask> detailTask(String id)
{
SysTask sysTask = taskRepository.findByJobGroup(id);
return Result.<SysTask>builder().success().data(sysTask).build();
}
/**
* @Method
* @Author www
* @Version 1.0
* @Description 删除定时任务
* @Return
* @Date 2020/8/27 10:38
*/
@Override
public Result<String> deleteTask(String id) throws SchedulerException
{
if(StringUtils.isNotEmpty(id))
{
SysTask sysTask = taskRepository.getOne(Long.valueOf(id));
String jobGroup = sysTask.getJobGroup();
taskRepository.delete(sysTask);
scheduler.deleteJob(ScheduleUtils.getJobKey(Long.valueOf(id), jobGroup));
}
return Result.<String>builder().success().build();
}
/**
* @Method
* @Author www
* @Version 1.0
* @Description 批量删除定时任务
* @Return
* @Date 2020/8/19 9:03
*/
@Override
public Result<String> deleteTaskByIds(String ids) throws SchedulerException
{
if(StringUtils.isNotEmpty(ids))
{
String[] id = ids.split(",");
for(int i=0;i<id.length;++i)
{
deleteTask(id[i]);
}
}
return Result.<String>builder().success().build();
}
@Override
public void run(String id)
{
try {
SysTask sysTask = taskRepository.getOne(Long.valueOf(id));
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES, sysTask);
scheduler.triggerJob(ScheduleUtils.getJobKey(Long.valueOf(id), sysTask.getJobGroup()), dataMap);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 更新任务
*
* @param sysTask 任务对象
* @param jobGroup 任务组名
*/
public void updateSchedulerJob(SysTask sysTask, String jobGroup) throws SchedulerException, TaskException
{
Long id = sysTask.getId();
// 判断是否存在
JobKey jobKey = ScheduleUtils.getJobKey(id, jobGroup);
if (scheduler.checkExists(jobKey))
{
// 防止创建时存在数据问题 先移除,然后在执行创建操作
scheduler.deleteJob(jobKey);
}
ScheduleUtils.createScheduleJob(scheduler, sysTask);
}
用到的utils以及实体类
package com.nhiot.service.quartz;
import com.nhiot.constants.ScheduleConstants;
import com.nhiot.entity.quartz.SysTask;
import com.nhiot.entity.quartz.SysTaskLog;
import com.nhiot.exception.ExceptionUtil;
import com.nhiot.repository.quartz.TaskLogRepository;
import com.nhiot.spring.SpringUtils;
import com.nhiot.util.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
/**
* 抽象quartz调用
*
* @author www
*/
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
{
SysTask sysTask = new SysTask();
BeanUtils.copyProperties(context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES),sysTask);
try
{
before(context, sysTask);
if (sysTask != null)
{
doExecute(context, sysTask);
}
after(context, sysTask, null);
}
catch (Exception e)
{
log.error("任务执行异常 - :", e);
after(context, sysTask, e);
}
}
/**
* 执行前
*
* @param context 工作执行上下文对象
* @param sysTask 系统计划任务
*/
protected void before(JobExecutionContext context, SysTask sysTask)
{
System.out.println(sysTask.getJobName());
threadLocal.set(new Date());
}
/**
* 执行后
*
* @param context 工作执行上下文对象
* @param sysTask 系统计划任务
*/
protected void after(JobExecutionContext context, SysTask sysTask, Exception e)
{
Date startTime = threadLocal.get();
threadLocal.remove();
final SysTaskLog sysTaskLog = new SysTaskLog();
sysTaskLog.setJobName(sysTask.getJobName());
sysTaskLog.setJobGroup(sysTask.getJobGroup());
sysTaskLog.setInvokeTarget(sysTask.getBeanClass());
sysTaskLog.setStartTime(startTime);
sysTaskLog.setEndTime(new Date());
long runMs = sysTaskLog.getEndTime().getTime() - sysTaskLog.getStartTime().getTime();
sysTaskLog.setJobMessage(sysTaskLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
if (e != null)
{
sysTaskLog.setStatus("1");
e.printStackTrace();
String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
sysTaskLog.setExceptionInfo(errorMsg);
}
else
{
sysTaskLog.setStatus("0");
}
// 写入数据库当中
SpringUtils.getBean(TaskLogRepository.class).saveAndFlush(sysTaskLog);
}
/**
* 执行方法,由子类重载
*
* @param context 工作执行上下文对象
* @param sysTask 系统计划任务
* @throws Exception 执行过程中的异常
*/
protected abstract void doExecute(JobExecutionContext context, SysTask sysTask) throws Exception;
}
CronUtils
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());
}
}
/**
* 修改定时任务时间
*/
public static String resetCronExpression(String cronExpression)
{
String[] str = cronExpression.split(" ");
StringBuffer re = new StringBuffer();
str[1]= String.valueOf(DateUtils.getMinute(new Date()));
for (int i=0;i<str.length;++i) {
if(i==0) {
re.append(str[i]);
}else {
re.append(" "+str[i]);
}
}
return re.toString();
}
}
JobInvokeUtils
public class JobInvokeUtil
{
/**
* 执行方法
*
* @param sysTask 系统任务
*/
public static void invokeMethod(SysTask sysTask) throws Exception
{
String invokeTarget = sysTask.getBeanClass();
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 ( methodParams!=null &&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 invokeTarget 名称
* @return true是 false否
*/
public static boolean isValidClassName(String invokeTarget)
{
return StringUtils.countMatches(invokeTarget, ".") > 1;
}
/**
* 获取bean名称
*
* @param invokeTarget 目标字符串
* @return bean名称
*/
public static String getBeanName(String invokeTarget)
{
String beanName = StringUtils.substringBefore(invokeTarget, "(");
return StringUtils.substringBeforeLast(beanName, ".");
}
/**
* 获取bean方法
*
* @param invokeTarget 目标字符串
* @return method方法
*/
public static String getMethodName(String invokeTarget)
{
String methodName = StringUtils.substringBefore(invokeTarget, "(");
return StringUtils.substringAfterLast(methodName, ".");
}
/**
* 获取method方法参数相关列表
*
* @param invokeTarget 目标字符串
* @return method方法相关参数列表
*/
public static List<Object[]> getMethodParams(String invokeTarget)
{
String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
if (StringUtils.isEmpty(methodStr))
{
return null;
}
String[] methodParams = methodStr.split(",");
List<Object[]> classs = new LinkedList<>();
for (int i = 0; i < methodParams.length; i++)
{
String str = StringUtils.trimToEmpty(methodParams[i]);
// String字符串类型,包含'
if (StringUtils.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;
}
}
QuartzDisallowConcurrentExecution:
/**
* 定时任务处理(禁止并发执行)
*
* @author www
*
*/
@DisallowConcurrentExecution
public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysTask sysTask) throws Exception
{
JobInvokeUtil.invokeMethod(sysTask);
}
}
QuartzJobExecution:
/**
* 定时任务处理(允许并发执行)
*
* @author www
*
*/
public class QuartzJobExecution extends AbstractQuartzJob
{
@Override
protected void doExecute(JobExecutionContext context, SysTask sysTask) throws Exception
{
JobInvokeUtil.invokeMethod(sysTask);
}
}
ScheduleUtils:
/**
* 定时任务工具类
*
* @author www
*
*/
public class ScheduleUtils
{
/**
* 得到quartz任务类
*
* @param sysTask 执行计划
* @return 具体执行任务类
*/
private static Class<? extends Job> getQuartzJobClass(SysTask sysTask)
{
boolean isConcurrent = "0".equals(sysTask.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, SysTask sysTask) throws SchedulerException, TaskException
{
Class<? extends Job> jobClass = getQuartzJobClass(sysTask);
// 构建job信息
Long id = sysTask.getId();
String jobGroup = sysTask.getJobGroup();
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(id, jobGroup)).build();
// 表达式调度构建器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(sysTask.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(sysTask, cronScheduleBuilder);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(id, jobGroup))
.withSchedule(cronScheduleBuilder).build();
// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, sysTask);
// 判断是否存在
if (scheduler.checkExists(getJobKey(id, jobGroup)))
{
// 防止创建时存在数据问题 先移除,然后在执行创建操作
scheduler.deleteJob(getJobKey(id, jobGroup));
}
scheduler.scheduleJob(jobDetail, trigger);
// 暂停任务
if (sysTask.getJobStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
{
scheduler.pauseJob(ScheduleUtils.getJobKey(id, jobGroup));
}
}
/**
* 设置定时任务策略
*/
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysTask sysTask, CronScheduleBuilder cb)
throws TaskException
{
switch (sysTask.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 '" + sysTask.getMisfirePolicy()
+ "' cannot be used in cron schedule tasks", TaskException.Code.CONFIG_ERROR);
}
}
}
效果:
更多推荐
所有评论(0)