mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-17 12:35:07 +08:00
1. 同步最新的表结构
2. 记录执行日志
This commit is contained in:
@ -1,7 +1,5 @@
|
||||
package cn.iocoder.dashboard.framework.quartz.core.handler;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
|
||||
/**
|
||||
* 任务处理器
|
||||
*
|
||||
@ -16,6 +14,6 @@ public interface JobHandler {
|
||||
* @return 结果
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
CommonResult<String> execute(String param) throws Exception;
|
||||
String execute(String param) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
package cn.iocoder.dashboard.framework.quartz.core.handler;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.common.exception.ServiceException;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.quartz.core.enums.JobDataKeyEnum;
|
||||
import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -19,8 +15,8 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.diff;
|
||||
import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCauseMessage;
|
||||
|
||||
/**
|
||||
* 基础 Job 调用者,负责调用 {@link JobHandler#execute(String)} 执行任务
|
||||
@ -40,68 +36,68 @@ public class JobHandlerInvoker extends QuartzJobBean {
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext executionContext) throws JobExecutionException {
|
||||
// 获得 Job 数据
|
||||
// 1. 获得 jobId 参数
|
||||
String jobIdStr = getJobData(executionContext, JobDataKeyEnum.JOB_ID);
|
||||
if (NumberUtil.isNumber(jobIdStr)) {
|
||||
log.error("[executeInternal][Job({}) 获取不到正确的 jobId({})]", executionContext.getJobDetail().getKey(), jobIdStr);
|
||||
throw new IllegalStateException(StrUtil.format("Job({}) 获取不到正确的 jobId({})",
|
||||
executionContext.getJobDetail().getKey(), jobIdStr));
|
||||
// 第一步,获得 Job 数据
|
||||
Long jobId = executionContext.getMergedJobDataMap().getLong(JobDataKeyEnum.JOB_ID.name());
|
||||
String jobHandlerName = getJobHandlerName(executionContext);
|
||||
String jobHandlerParam = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_PARAM.name());
|
||||
|
||||
// 第二步,执行任务
|
||||
Long jobLogId = null;
|
||||
Date startTime = new Date();
|
||||
String data = null;
|
||||
Throwable exception = null;
|
||||
try {
|
||||
// 记录 Job 日志(初始)
|
||||
jobLogId = jobLogFrameworkService.createJobLog(jobId, startTime, jobHandlerName, jobHandlerParam);
|
||||
// 执行任务
|
||||
data = this.executeInternal(jobHandlerName, jobHandlerParam);
|
||||
} catch (Throwable ex) {
|
||||
exception = ex;
|
||||
}
|
||||
Long jobId = Long.valueOf(jobIdStr);
|
||||
// 2. 获得 jobHandlerName 参数
|
||||
String jobHandlerName = getJobData(executionContext, JobDataKeyEnum.JOB_HANDLER_NAME);
|
||||
|
||||
// 第三步,记录执行日志
|
||||
this.updateJobLogResultAsync(jobLogId, startTime, data, exception, executionContext);
|
||||
|
||||
// 最终还是抛出异常,用于停止任务
|
||||
if (exception != null) {
|
||||
throw new JobExecutionException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getJobHandlerName(JobExecutionContext executionContext) {
|
||||
String jobHandlerName = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_NAME.name());
|
||||
if (StrUtil.isEmpty(jobHandlerName)) {
|
||||
log.error("[executeInternal][Job({}) 获取不到正确的 jobHandlerName({})]", executionContext.getJobDetail().getKey(), jobHandlerName);
|
||||
log.error("[executeInternal][Job({}) 获取不到正确的 jobHandlerName({})]",
|
||||
executionContext.getJobDetail().getKey(), jobHandlerName);
|
||||
throw new IllegalStateException(StrUtil.format("Job({}) 获取不到正确的 jobHandlerName({})",
|
||||
executionContext.getJobDetail().getKey(), jobHandlerName));
|
||||
}
|
||||
// 3. 获得 jobHandlerParam 参数
|
||||
String jobHandlerParam = getJobData(executionContext, JobDataKeyEnum.JOB_HANDLER_PARAM);
|
||||
|
||||
Long jobLogId = null;
|
||||
Date startTime = new Date();
|
||||
try {
|
||||
// 记录 Job 日志(初始)
|
||||
jobLogId = jobLogFrameworkService.createJobLog(jobId, jobHandlerName, jobHandlerParam);
|
||||
// 执行任务
|
||||
String data = this.executeInternal(jobId, jobHandlerName, jobHandlerParam);
|
||||
// 标记 Job 日志(成功)
|
||||
Date endTime = new Date();
|
||||
jobLogFrameworkService.updateJobLogSuccessAsync(jobLogId, endTime, diff(endTime, startTime), data);
|
||||
} catch (ServiceException serviceException) {
|
||||
// 标记 Job 日志(异常)
|
||||
Date endTime = new Date();
|
||||
jobLogFrameworkService.updateJobLogErrorAsync(jobLogId, endTime, diff(endTime, startTime),
|
||||
serviceException.getCode(), serviceException.getMessage());
|
||||
// 最终还是抛出异常,用于停止任务
|
||||
throw serviceException;
|
||||
} catch (Throwable e) {
|
||||
// 标记 Job 日志(异常)
|
||||
Date endTime = new Date();
|
||||
jobLogFrameworkService.updateJobLogErrorAsync(jobLogId, endTime, diff(endTime, startTime),
|
||||
INTERNAL_SERVER_ERROR.getCode(), ExceptionUtil.getRootCauseMessage(e));
|
||||
// 最终还是抛出异常,用于停止任务
|
||||
throw new JobExecutionException(e);
|
||||
}
|
||||
return jobHandlerName;
|
||||
}
|
||||
|
||||
private String executeInternal(Long jobId, String jobHandlerName, String jobHandlerParam) throws Exception {
|
||||
private String executeInternal(String jobHandlerName, String jobHandlerParam) throws Exception {
|
||||
// 获得 JobHandler 对象
|
||||
JobHandler jobHandler = applicationContext.getBean(jobHandlerName, JobHandler.class);
|
||||
Assert.isNull(jobHandler, "JobHandler 不会为空");
|
||||
|
||||
Assert.notNull(jobHandler, "JobHandler 不会为空");
|
||||
// 执行任务
|
||||
CommonResult<String> result = jobHandler.execute(jobHandlerParam);
|
||||
// 如果执行失败,则抛出 ServiceException 异常,方便统一记录
|
||||
if (result.isError()) {
|
||||
throw new ServiceException(result.getCode(), result.getMsg());
|
||||
}
|
||||
return result.getData();
|
||||
return jobHandler.execute(jobHandlerParam);
|
||||
}
|
||||
|
||||
private static String getJobData(JobExecutionContext executionContext, JobDataKeyEnum key) {
|
||||
return executionContext.getMergedJobDataMap().getString(key.name());
|
||||
private void updateJobLogResultAsync(Long jobLogId, Date startTime, String data, Throwable exception,
|
||||
JobExecutionContext executionContext) {
|
||||
Date endTime = new Date();
|
||||
try {
|
||||
if (data != null) { // 成功
|
||||
jobLogFrameworkService.updateJobLogSuccessAsync(jobLogId, endTime, (int) diff(endTime, startTime), data);
|
||||
} else { // 失败
|
||||
jobLogFrameworkService.updateJobLogErrorAsync(jobLogId, endTime, (int) diff(endTime, startTime),
|
||||
getRootCauseMessage(exception));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("[executeInternal][Job({}) logId({}) 记录执行日志失败({})]",
|
||||
executionContext.getJobDetail().getKey(), jobLogId,
|
||||
data != null ? data : getRootCauseMessage(exception));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.dashboard.framework.quartz.core.service;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -13,31 +15,40 @@ public interface JobLogFrameworkService {
|
||||
* 创建 Job 日志
|
||||
*
|
||||
* @param jobId 任务编号
|
||||
* @param beginTime 开始时间
|
||||
* @param jobHandlerName Job 处理器的名字
|
||||
* @param jobHandlerParam Job 处理器的参数
|
||||
* @return Job 日志的编号
|
||||
*/
|
||||
Long createJobLog(Long jobId, String jobHandlerName, String jobHandlerParam);
|
||||
Long createJobLog(@NotNull(message = "任务编号不能为空") Long jobId,
|
||||
@NotNull(message = "开始时间") Date beginTime,
|
||||
@NotEmpty(message = "Job 处理器的名字不能为空") String jobHandlerName,
|
||||
String jobHandlerParam);
|
||||
|
||||
/**
|
||||
* 更新 Job 日志成功
|
||||
*
|
||||
* @param id 日志编号
|
||||
* @param logId 日志编号
|
||||
* @param endTime 结束时间。因为是异步,避免记录时间不准去
|
||||
* @param duration 运行时长,单位:毫秒
|
||||
* @param data 成功数据
|
||||
* @param result 成功数据
|
||||
*/
|
||||
void updateJobLogSuccessAsync(Long id, Date endTime, Long duration, String data);
|
||||
void updateJobLogSuccessAsync(@NotNull(message = "日志编号不能为空") Long logId,
|
||||
@NotNull(message = "结束时间不能为空") Date endTime,
|
||||
@NotNull(message = "运行时长不能为空") Integer duration,
|
||||
String result);
|
||||
|
||||
/**
|
||||
* 更新 Job 日志失败
|
||||
*
|
||||
* @param id 日志编号
|
||||
* @param logId 日志编号
|
||||
* @param endTime 结束时间。因为是异步,避免记录时间不准去
|
||||
* @param duration 运行时长,单位:毫秒
|
||||
* @param code 错误码
|
||||
* @param msg 异常提示
|
||||
* @param result 异常提示
|
||||
*/
|
||||
void updateJobLogErrorAsync(Long id, Date endTime, Long duration, Integer code, String msg);
|
||||
void updateJobLogErrorAsync(@NotNull(message = "日志编号不能为空") Long logId,
|
||||
@NotNull(message = "结束时间不能为空") Date endTime,
|
||||
@NotNull(message = "运行时长不能为空") Integer duration,
|
||||
String result);
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package cn.iocoder.dashboard.modules.infra.dal.dataobject.job;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.dashboard.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -18,6 +17,9 @@ import java.util.Date;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfJobLogDO extends BaseDO {
|
||||
|
||||
/**
|
||||
@ -46,7 +48,7 @@ public class InfJobLogDO extends BaseDO {
|
||||
/**
|
||||
* 开始执行时间
|
||||
*/
|
||||
private Date startTime;
|
||||
private Date beginTime;
|
||||
/**
|
||||
* 结束执行时间
|
||||
*/
|
||||
@ -56,16 +58,16 @@ public class InfJobLogDO extends BaseDO {
|
||||
*/
|
||||
private Integer duration;
|
||||
/**
|
||||
* 结果码
|
||||
* 状态
|
||||
*
|
||||
* 目前使用的 {@link CommonResult#getCode()} 属性
|
||||
* 枚举 {@link InfJobLogStatusEnum}
|
||||
*/
|
||||
private Integer resultCode;
|
||||
private Integer status;
|
||||
/**
|
||||
* 结果
|
||||
* 结果数据
|
||||
*
|
||||
* 成功时,使用 {@link CommonResult#getData()} 数据
|
||||
* 失败时,使用 {@link CommonResult#getMsg()} 属性
|
||||
* 成功时,使用 {@link JobHandler#execute(String)} 的结果
|
||||
* 失败时,使用 {@link JobHandler#execute(String)} 的异常堆栈
|
||||
*/
|
||||
private String result;
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
package cn.iocoder.dashboard.modules.infra.dal.mysql.job;
|
||||
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 任务日志 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfJobLogMapper extends BaseMapperX<InfJobLogDO> {
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.dashboard.modules.infra.enums.job;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 任务日志的状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum InfJobLogStatusEnum {
|
||||
|
||||
RUNNING(0), // 运行中
|
||||
SUCCESS(1), // 成功
|
||||
FAILURE(2); // 失败
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cn.iocoder.dashboard.modules.infra.service.job;
|
||||
|
||||
import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService;
|
||||
|
||||
/**
|
||||
* Job 日志 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface InfJobLogService extends JobLogFrameworkService {
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package cn.iocoder.dashboard.modules.infra.service.job.impl;
|
||||
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper;
|
||||
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum;
|
||||
import cn.iocoder.dashboard.modules.infra.service.job.InfJobLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Job 日志 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class InfJobLogServiceImpl implements InfJobLogService {
|
||||
|
||||
@Resource
|
||||
private InfJobLogMapper jobLogMapper;
|
||||
|
||||
@Override
|
||||
public Long createJobLog(Long jobId, Date beginTime, String jobHandlerName, String jobHandlerParam) {
|
||||
InfJobLogDO log = InfJobLogDO.builder().jobId(jobId).handlerName(jobHandlerName).handlerParam(jobHandlerParam)
|
||||
.beginTime(beginTime).status(InfJobLogStatusEnum.RUNNING.getStatus()).build();
|
||||
jobLogMapper.insert(log);
|
||||
return log.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void updateJobLogSuccessAsync(Long logId, Date endTime, Integer duration, String result) {
|
||||
updateJobLogResult(logId, endTime, duration, result, InfJobLogStatusEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void updateJobLogErrorAsync(Long logId, Date endTime, Integer duration, String result) {
|
||||
updateJobLogResult(logId, endTime, duration, result, InfJobLogStatusEnum.FAILURE);
|
||||
}
|
||||
|
||||
private void updateJobLogResult(Long logId, Date endTime, Integer duration, String result, InfJobLogStatusEnum status) {
|
||||
try {
|
||||
InfJobLogDO updateObj = InfJobLogDO.builder().id(logId).endTime(endTime).duration(duration)
|
||||
.status(status.getStatus()).result(result).build();
|
||||
jobLogMapper.updateById(updateObj);
|
||||
} catch (Exception ex) {
|
||||
log.error("[updateJobLogResult][logId({}) endTime({}) duration({}) result({}) status({})]",
|
||||
logId, endTime, duration, result, status);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.dashboard.modules.system.job.auth;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.quartz.core.handler.JobHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -15,7 +14,7 @@ import org.springframework.stereotype.Component;
|
||||
public class SysUserSessionTimeoutJob implements JobHandler {
|
||||
|
||||
@Override
|
||||
public CommonResult<String> execute(String param) throws Exception {
|
||||
public String execute(String param) throws Exception {
|
||||
// System.out.println("执行了一次任务");
|
||||
log.info("[execute][执行任务:{}]", param);
|
||||
return null;
|
||||
|
@ -18,7 +18,7 @@ public class DateUtils {
|
||||
return System.currentTimeMillis() > time.getTime();
|
||||
}
|
||||
|
||||
public static Long diff(Date endTime, Date startTime) {
|
||||
public static long diff(Date endTime, Date startTime) {
|
||||
return endTime.getTime() - startTime.getTime();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user