quartz监控日志(一)
quartz监控日志(二)添加监听器
quartz监控日志(三)查看卡死线程堆栈
上面几章介绍了quartz监控的几种方式,下面再介绍一种监听方式:自定义QuartzJobBean
一、自定义QuartzJobBean
代码语言:javascript复制/**
* 定时任务处理
*
* @author lipeng
*
*/
@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);
}
}
}
SysJobLog
代码语言:javascript复制/**
* 定时任务调度日志表 sys_job_log
*
* @author lipeng
*/
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 methodName;
/** 方法参数 */
@Excel(name = "方法参数")
private String methodParams;
/** 日志信息 */
@Excel(name = "日志信息")
private String jobMessage;
/** 执行状态(0正常 1失败) */
@Excel(name = "执行状态", readConverterExp = "0=正常,1=失败")
private String status;
/** 异常信息 */
@Excel(name = "异常信息")
private String exceptionInfo;
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 getMethodName()
{
return methodName;
}
public void setMethodName(String methodName)
{
this.methodName = methodName;
}
public String getMethodParams()
{
return methodParams;
}
public void setMethodParams(String methodParams)
{
this.methodParams = methodParams;
}
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;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("jobLogId", getJobLogId())
.append("jobName", getJobName())
.append("jobGroup", getJobGroup())
.append("methodName", getMethodName())
.append("methodParams", getMethodParams())
.append("jobMessage", getJobMessage())
.append("status", getStatus())
.append("exceptionInfo", getExceptionInfo())
.append("createTime", getCreateTime())
.toString();
}
}
ScheduleRunnable
代码语言:javascript复制/**
* 执行定时任务
*
* @author lipeng
*
*/
public class ScheduleRunnable implements Runnable
{
private static final Logger log = LoggerFactory.getLogger(ScheduleRunnable.class);
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)
{
log.error("执行定时任务 - :", e);
}
}
}
二、创建job
代码语言:javascript复制 /**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, SysJob job)
{
try
{
// 构建job信息
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);
}
}
三、将数据库中的job初始化
代码语言:javascript复制 /**
* 项目启动时,初始化定时器
*/
@PostConstruct
public void init()
{
List<SysJob> jobList = jobMapper.selectJobAll();
for (SysJob job : jobList)
{
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, job.getJobId());
// 如果不存在,则创建
if (cronTrigger == null)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
else
{
ScheduleUtils.updateScheduleJob(scheduler, job);
}
}
}
ScheduleUtils源代码如下:
代码语言:javascript复制/**
* 定时任务工具类
*
* @author lipeng
*
*/
public class ScheduleUtils
{
private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
/**
* 获取触发器key
*/
public static TriggerKey getTriggerKey(Long jobId)
{
return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME jobId);
}
/**
* 获取jobKey
*/
public static JobKey getJobKey(Long jobId)
{
return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME jobId);
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId)
{
try
{
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
}
catch (SchedulerException e)
{
log.error("getCronTrigger 异常:", e);
}
return null;
}
/**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, SysJob job)
{
try
{
// 构建job信息
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)
{
try
{
TriggerKey triggerKey = getTriggerKey(job.getJobId());
// 表达式调度构建器
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)
{
log.error("SchedulerException 异常:", e);
}
catch (TaskException e)
{
log.error("SchedulerException 异常:", e);
}
}
/**
* 立即执行任务
*/
public static int run(Scheduler scheduler, SysJob job)
{
int rows = 0;
try
{
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES, job);
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)
{
try
{
scheduler.pauseJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("pauseJob 异常:", e);
}
}
/**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.resumeJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("resumeJob 异常:", e);
}
}
/**
* 删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.deleteJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("deleteScheduleJob 异常:", e);
}
}
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);
}
}
}