目录
1、建表脚本
2、代码实现
2.1、实体类JobLog.java
2.2、业务类接口及实现类
2.3、持久层
2.4、自动记录日志超类
2.5、自定义job类
3、执行结果
/*==============================================================*/
/* Table: sys_job_log */
/*==============================================================*/
create table sys_job_log
(
id varchar(64) not null comment '定时任务日志主键',
job_name varchar(512) comment '任务名称',
trig_name varchar(512) comment '触发器名称',
start_time datetime comment '开始时间',
end_time datetime comment '结束时间',
content text comment '执行情况',
status varchar(64) comment '状态',
duration decimal(11) comment '持续时间',
primary key (id)
);
alter table sys_job_log comment '定时任务日志';
代码基于MyBatis-Plus框架编写,基于模版模式进行实现一个超类,后续自定义job只需要继承该超类即可实现自动记录日志逻辑。
@Data
@TableName("sys_job_log")
@ApiModel(value="sys_job_log对象", description="定时任务日志")
public class JobLog implements Serializable {
private static final long serialVersionUID = 1L;
/**定时任务日志主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "定时任务日志主键")
private String id;
/**任务名称*/
@ApiModelProperty(value = "任务名称")
private String jobName;
/**触发器名称*/
@ApiModelProperty(value = "触发器名称")
private String trigName;
/**开始时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "开始时间")
private Date startTime;
/**结束时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "结束时间")
private Date endTime;
/**执行情况*/
@ApiModelProperty(value = "执行情况")
private String content;
/**状态*/
@ApiModelProperty(value = "状态{0:失败,1:成功}")
private String status;
/**持续时间,单位:秒*/
@ApiModelProperty(value = "持续时间,单位:秒")
private Long duration;
}
public interface IJobLogService extends IService {
/** 执行状态:成功*/
public static final String STATUS_SUCCESS = "1";
/** 执行状态:失败*/
public static final String STATUS_FAIL = "0";
}
@Service
public class JobLogServiceImpl extends ServiceImpl implements IJobLogService {
}
public interface JobLogMapper extends BaseMapper {
}
@Slf4j
@DisallowConcurrentExecution
public abstract class AbstractQuartzJob implements Job {
public static final String RUN_MSG = "runMsg";
@Resource
private IJobLogService jobService;
public AbstractQuartzJob() {
}
public abstract void executeJob(JobExecutionContext context) throws Exception;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 开始时间毫秒
long startTimeMillis = System.currentTimeMillis();
// 开始时间
Date startTime = new Date();
// 任务名称
String jobName = context.getJobDetail().getKey().getName();
// 触发器名称
String trigName = "directExec";
Trigger trig = context.getTrigger();
if (BeanUtil.isNotEmpty(trig)) {
trigName = trig.getKey().getName();
}
try {
// 执行业务逻辑
executeJob(context);
// 获取执行日志
String runMsg = (String) context.getJobDetail().getJobDataMap().get(RUN_MSG);
// 结束时间毫秒
long endTimeMillis = System.currentTimeMillis();
// 结束时间
Date endTime = new Date();
// 计算执行时长
long duration = (endTimeMillis - startTimeMillis) / 1000;
// 记录日志
addLog(jobName, trigName, startTime, endTime, duration, "任务执行成功!\r\n" + runMsg, IJobLogService.STATUS_SUCCESS);
} catch (Exception ex) {
// 结束时间毫秒
long endTimeMillis = System.currentTimeMillis();
// 结束时间
Date endTime = new Date();
// 计算执行时长
long duration = (endTimeMillis - startTimeMillis) / 1000;
// 记录日志
addLog(jobName, trigName, startTime, endTime, duration, "任务执行失败!\r\n" + getExceptionInfo(ex), IJobLogService.STATUS_FAIL);
log.error("执行任务出错:" ,ex);
}
}
private void addLog(String jobName, String trigName, Date strStartTime, Date strEndTime, long duration, String content, String status) {
JobLog jobLog = new JobLog();
jobLog.setJobName(jobName);
jobLog.setTrigName(trigName);
jobLog.setStartTime(strStartTime);
jobLog.setEndTime(strEndTime);
jobLog.setDuration(duration);
jobLog.setContent(content);
jobLog.setStatus(status);
jobService.save(jobLog);
}
/**
* @param e Exception
* @return 异常内容
* @category 获取try-catch中的异常内容
*/
public static String getExceptionInfo(Throwable e) {
String ret = "";
if (BeanUtil.isEmpty(e)) {
return ret;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream pout = new PrintStream(out);
try {
e.printStackTrace(pout);
ret = new String(out.toByteArray());
} catch (Exception ex) {
log.error("获取异常信息错误",ex);
}finally {
pout.close();
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return ret;
}
}
@Slf4j
public class SampleJob extends AbstractQuartzJob {
@Override
public void executeJob(JobExecutionContext context) throws JobExecutionException {
StringBuilder runLog = new StringBuilder();
runLog.append("开始执行定时任务").append("\r\n");
runLog.append("====================================================").append("\r\n");
runLog.append(String.format(" 普通定时任务 SampleJob 执行成功 ! 时间:" + DateUtils.getTimestamp())).append("\r\n");
// TODO 定时任务逻辑
runLog.append("====================================================").append("\r\n");
context.getJobDetail().getJobDataMap().put(RUN_MSG,runLog.toString());
}
}
id:1
job_name:com.quartz.job.SampleJob20230708075629
trig_name:com.quartz.job.SampleJob20230708075629
start_time:2023-07-08 15:56:32
end_time:2023-07-08 15:56:47
content: 任务执行成功!
开始执行定时任务
====================================================
普通定时任务SampleJob执行成功! 时间:2023-07-08 15:56:32
====================================================
status:1
duration:15