增加服务器管理认证方式,增加测试连接接口

This commit is contained in:
dengqichen 2025-10-30 17:07:31 +08:00
parent 10bfa7bcbd
commit bd7733d7d7
4 changed files with 160 additions and 104 deletions

View File

@ -89,6 +89,18 @@ public class ScheduleJobApiController extends BaseController<ScheduleJob, Schedu
return Response.success(); return Response.success();
} }
/**
* 恢复启用禁用任务
*/
@Operation(summary = "启用定时任务", description = "恢复被禁用DISABLED的定时任务重新注册调度状态变为ENABLED")
@PostMapping("/{id}/enable")
public Response<Void> enableJob(
@Parameter(description = "任务ID", required = true) @PathVariable Long id
) {
scheduleJobService.enableJob(id);
return Response.success();
}
/** /**
* 立即触发任务 * 立即触发任务
*/ */

View File

@ -81,7 +81,7 @@ public class ScheduleJob extends Entity<Long> {
*/ */
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false, length = 20) @Column(name = "status", nullable = false, length = 20)
private ScheduleJobStatusEnum status = ScheduleJobStatusEnum.ENABLED; private ScheduleJobStatusEnum status;
/** /**
* 是否允许并发执行 * 是否允许并发执行

View File

@ -41,6 +41,12 @@ public interface IScheduleJobService extends IBaseService<ScheduleJob, ScheduleJ
*/ */
void disableJob(Long jobId); void disableJob(Long jobId);
/**
* 恢复启用解除禁用任务
* @param jobId 任务ID
*/
void enableJob(Long jobId);
/** /**
* 立即执行一次任务仅限ENABLED和PAUSED状态 * 立即执行一次任务仅限ENABLED和PAUSED状态
* *

View File

@ -40,13 +40,13 @@ import java.util.stream.Collectors;
/** /**
* 定时任务Service实现 * 定时任务Service实现
* *
* @author qichen * @author qichen
*/ */
@Slf4j @Slf4j
@Service @Service
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, ScheduleJobDTO, ScheduleJobQuery, Long> public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, ScheduleJobDTO, ScheduleJobQuery, Long>
implements IScheduleJobService { implements IScheduleJobService {
@Resource @Resource
private IScheduleJobRepository jobRepository; private IScheduleJobRepository jobRepository;
@ -80,7 +80,7 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
public ScheduleJobDTO create(ScheduleJobDTO dto) { public ScheduleJobDTO create(ScheduleJobDTO dto) {
// 检查任务名称唯一性 // 检查任务名称唯一性
if (jobRepository.existsByJobNameAndDeletedFalse(dto.getJobName())) { if (jobRepository.existsByJobNameAndDeletedFalse(dto.getJobName())) {
throw new BusinessException(ResponseCode.DATA_ALREADY_EXISTS, new Object[]{"任务名称", dto.getJobName()}); throw new BusinessException(ResponseCode.DATA_ALREADY_EXISTS, new Object[] {"任务名称", dto.getJobName()});
} }
return super.create(dto); return super.create(dto);
} }
@ -91,34 +91,34 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 1. 查询旧数据 // 1. 查询旧数据
ScheduleJob oldJob = findEntityById(id); ScheduleJob oldJob = findEntityById(id);
ScheduleJobStatusEnum oldStatus = oldJob.getStatus(); ScheduleJobStatusEnum oldStatus = oldJob.getStatus();
// 2. 检查是否试图修改 status强制拦截 // 2. 检查是否试图修改 status强制拦截
if (dto.getStatus() != null && dto.getStatus() != oldStatus) { if (dto.getStatus() != null && dto.getStatus() != oldStatus) {
throw new BusinessException(ResponseCode.SCHEDULE_JOB_STATUS_CANNOT_UPDATE, throw new BusinessException(ResponseCode.SCHEDULE_JOB_STATUS_CANNOT_UPDATE,
new Object[]{"请使用 /start、/pause、/resume、/disable 接口管理任务状态"}); new Object[] {"请使用 /start、/pause、/resume、/disable 接口管理任务状态"});
} }
// 3. 强制保持原状态防止前端传入 // 3. 强制保持原状态防止前端传入
dto.setStatus(oldStatus); dto.setStatus(oldStatus);
// 4. 更新数据库 // 4. 更新数据库
ScheduleJobDTO updated = super.update(id, dto); ScheduleJobDTO updated = super.update(id, dto);
// 5. 只有非 DISABLED 状态才需要重新调度 // 5. 只有非 DISABLED 状态才需要重新调度
if (oldStatus != ScheduleJobStatusEnum.DISABLED) { if (oldStatus != ScheduleJobStatusEnum.DISABLED) {
try { try {
JobKey jobKey = getJobKey(id); JobKey jobKey = getJobKey(id);
if (scheduler.checkExists(jobKey)) { if (scheduler.checkExists(jobKey)) {
ScheduleJob job = findEntityById(id); ScheduleJob job = findEntityById(id);
// 先删除旧的Job // 先删除旧的Job
scheduler.deleteJob(jobKey); scheduler.deleteJob(jobKey);
// 重新创建JobDetail使用最新参数 // 重新创建JobDetail使用最新参数
JobDetail jobDetail = JobBuilder.newJob(DynamicJob.class) JobDetail jobDetail = JobBuilder.newJob(DynamicJob.class)
.withIdentity(jobKey) .withIdentity(jobKey)
.withDescription(job.getJobDescription()) .withDescription(job.getJobDescription())
.build(); .build();
// 设置最新的JobDataMap // 设置最新的JobDataMap
jobDetail.getJobDataMap().put("jobId", job.getId()); jobDetail.getJobDataMap().put("jobId", job.getId());
@ -129,18 +129,18 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 重新创建Trigger // 重新创建Trigger
Trigger trigger = TriggerBuilder.newTrigger() Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(getTriggerKey(id)) .withIdentity(getTriggerKey(id))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())) .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
.build(); .build();
// 重新调度 // 重新调度
scheduler.scheduleJob(jobDetail, trigger); scheduler.scheduleJob(jobDetail, trigger);
// 如果原来是 PAUSED重新调度后也要暂停 // 如果原来是 PAUSED重新调度后也要暂停
if (oldStatus == ScheduleJobStatusEnum.PAUSED) { if (oldStatus == ScheduleJobStatusEnum.PAUSED) {
scheduler.pauseJob(jobKey); scheduler.pauseJob(jobKey);
} }
log.info("任务配置已更新并重新调度jobId={}, jobName={}", job.getId(), job.getJobName()); log.info("任务配置已更新并重新调度jobId={}, jobName={}", job.getId(), job.getJobName());
} }
} catch (SchedulerException e) { } catch (SchedulerException e) {
@ -150,7 +150,7 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
} else { } else {
log.info("任务配置已更新DISABLED状态不调度jobId={}", id); log.info("任务配置已更新DISABLED状态不调度jobId={}", id);
} }
return updated; return updated;
} }
@ -160,34 +160,35 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 填充关联信息 // 填充关联信息
List<ScheduleJobDTO> content = page.getContent().stream() List<ScheduleJobDTO> content = page.getContent().stream()
.peek(job -> { .peek(job -> {
// 填充分类信息 // 填充分类信息
if (job.getCategoryId() != null) { if (job.getCategoryId() != null) {
Optional<ScheduleJobCategory> categoryOptional = categoryRepository.findById(job.getCategoryId()); Optional<ScheduleJobCategory> categoryOptional = categoryRepository.findById(job.getCategoryId());
categoryOptional.ifPresent(category -> job.setCategory(categoryConverter.toDto(category))); categoryOptional.ifPresent(category -> job.setCategory(categoryConverter.toDto(category)));
} }
// 填充表单信息 // 填充表单信息
if (job.getFormDefinitionId() != null) { if (job.getFormDefinitionId() != null) {
Optional<FormDefinition> formOptional = formDefinitionRepository.findById(job.getFormDefinitionId()); Optional<FormDefinition> formOptional = formDefinitionRepository.findById(job.getFormDefinitionId());
formOptional.ifPresent(form -> job.setFormDefinition(formDefinitionConverter.toDto(form))); formOptional.ifPresent(form -> job.setFormDefinition(formDefinitionConverter.toDto(form)));
} }
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
return new PageImpl<>(content, page.getPageable(), page.getTotalElements()); return new PageImpl<>(content, page.getPageable(), page.getTotalElements());
} }
@Override @Override
@Transactional
public void startJob(Long jobId) { public void startJob(Long jobId) {
try { try {
ScheduleJob job = findEntityById(jobId); ScheduleJob job = findEntityById(jobId);
// 创建JobDetail // 创建JobDetail
JobDetail jobDetail = JobBuilder.newJob(DynamicJob.class) JobDetail jobDetail = JobBuilder.newJob(DynamicJob.class)
.withIdentity(getJobKey(jobId)) .withIdentity(getJobKey(jobId))
.withDescription(job.getJobDescription()) .withDescription(job.getJobDescription())
.build(); .build();
// 设置JobDataMap // 设置JobDataMap
jobDetail.getJobDataMap().put("jobId", job.getId()); jobDetail.getJobDataMap().put("jobId", job.getId());
@ -198,19 +199,19 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 创建Trigger // 创建Trigger
Trigger trigger = TriggerBuilder.newTrigger() Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(getTriggerKey(jobId)) .withIdentity(getTriggerKey(jobId))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())) .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
.build(); .build();
// 调度任务 // 调度任务
scheduler.scheduleJob(jobDetail, trigger); scheduler.scheduleJob(jobDetail, trigger);
// 更新任务状态 // 更新任务状态
job.setStatus(ScheduleJobStatusEnum.ENABLED); job.setStatus(ScheduleJobStatusEnum.ENABLED);
jobRepository.save(job); jobRepository.save(job);
log.info("任务启动成功jobId={}, jobName={}", jobId, job.getJobName()); log.info("任务启动成功jobId={}, jobName={}", jobId, job.getJobName());
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("启动任务失败jobId={}", jobId, e); log.error("启动任务失败jobId={}", jobId, e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_START_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_START_FAILED);
@ -218,17 +219,18 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
} }
@Override @Override
@Transactional
public void pauseJob(Long jobId) { public void pauseJob(Long jobId) {
try { try {
scheduler.pauseJob(getJobKey(jobId)); scheduler.pauseJob(getJobKey(jobId));
// 更新任务状态 // 更新任务状态
ScheduleJob job = findEntityById(jobId); ScheduleJob job = findEntityById(jobId);
job.setStatus(ScheduleJobStatusEnum.PAUSED); job.setStatus(ScheduleJobStatusEnum.PAUSED);
jobRepository.save(job); jobRepository.save(job);
log.info("任务暂停成功jobId={}", jobId); log.info("任务暂停成功jobId={}", jobId);
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("暂停任务失败jobId={}", jobId, e); log.error("暂停任务失败jobId={}", jobId, e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_PAUSE_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_PAUSE_FAILED);
@ -236,17 +238,18 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
} }
@Override @Override
@Transactional
public void resumeJob(Long jobId) { public void resumeJob(Long jobId) {
try { try {
scheduler.resumeJob(getJobKey(jobId)); scheduler.resumeJob(getJobKey(jobId));
// 更新任务状态 // 更新任务状态
ScheduleJob job = findEntityById(jobId); ScheduleJob job = findEntityById(jobId);
job.setStatus(ScheduleJobStatusEnum.ENABLED); job.setStatus(ScheduleJobStatusEnum.ENABLED);
jobRepository.save(job); jobRepository.save(job);
log.info("任务恢复成功jobId={}", jobId); log.info("任务恢复成功jobId={}", jobId);
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("恢复任务失败jobId={}", jobId, e); log.error("恢复任务失败jobId={}", jobId, e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_RESUME_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_RESUME_FAILED);
@ -254,15 +257,16 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
} }
@Override @Override
@Transactional
public void disableJob(Long jobId) { public void disableJob(Long jobId) {
ScheduleJob job = findEntityById(jobId); ScheduleJob job = findEntityById(jobId);
// 幂等性检查 // 幂等性检查
if (job.getStatus() == ScheduleJobStatusEnum.DISABLED) { if (job.getStatus() == ScheduleJobStatusEnum.DISABLED) {
log.info("任务已经是禁用状态jobId={}, jobName={}", jobId, job.getJobName()); log.info("任务已经是禁用状态jobId={}, jobName={}", jobId, job.getJobName());
return; return;
} }
try { try {
// Quartz 删除任务 // Quartz 删除任务
JobKey jobKey = getJobKey(jobId); JobKey jobKey = getJobKey(jobId);
@ -270,19 +274,53 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
scheduler.deleteJob(jobKey); scheduler.deleteJob(jobKey);
log.info("从Quartz删除任务jobId={}, jobName={}", jobId, job.getJobName()); log.info("从Quartz删除任务jobId={}, jobName={}", jobId, job.getJobName());
} }
// 更新数据库状态 // 更新数据库状态
job.setStatus(ScheduleJobStatusEnum.DISABLED); job.setStatus(ScheduleJobStatusEnum.DISABLED);
jobRepository.save(job); jobRepository.save(job);
log.info("任务已禁用jobId={}, jobName={}", jobId, job.getJobName()); log.info("任务已禁用jobId={}, jobName={}", jobId, job.getJobName());
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("禁用任务失败jobId={}, jobName={}", jobId, job.getJobName(), e); log.error("禁用任务失败jobId={}, jobName={}", jobId, job.getJobName(), e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_DISABLE_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_DISABLE_FAILED);
} }
} }
@Override
@Transactional
public void enableJob(Long jobId) {
ScheduleJob job = findEntityById(jobId);
if (job.getStatus() != ScheduleJobStatusEnum.DISABLED) {
throw new BusinessException(ResponseCode.SCHEDULE_JOB_STATUS_CANNOT_UPDATE, new Object[] {"仅禁用状态任务可启用"});
}
try {
// 创建并调度新Job
JobDetail jobDetail = JobBuilder.newJob(DynamicJob.class)
.withIdentity(getJobKey(jobId))
.withDescription(job.getJobDescription())
.build();
jobDetail.getJobDataMap().put("jobId", job.getId());
jobDetail.getJobDataMap().put("jobName", job.getJobName());
jobDetail.getJobDataMap().put("beanName", job.getBeanName());
jobDetail.getJobDataMap().put("methodName", job.getMethodName());
jobDetail.getJobDataMap().put("methodParams", job.getMethodParams());
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(getTriggerKey(jobId))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
.build();
scheduler.scheduleJob(jobDetail, trigger);
job.setStatus(ScheduleJobStatusEnum.ENABLED);
jobRepository.save(job);
log.info("任务从DISABLED恢复启用成功jobId={}, jobName={}", jobId, job.getJobName());
} catch (SchedulerException e) {
log.error("恢复启用任务失败jobId={}, jobName={}", jobId, job.getJobName(), e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_START_FAILED);
}
}
@Override @Override
public void triggerJob(Long jobId) { public void triggerJob(Long jobId) {
// 检查任务状态 // 检查任务状态
@ -291,11 +329,11 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
log.warn("禁用状态的任务不允许触发jobId={}, jobName={}", jobId, job.getJobName()); log.warn("禁用状态的任务不允许触发jobId={}, jobName={}", jobId, job.getJobName());
throw new BusinessException(ResponseCode.SCHEDULE_JOB_DISABLED_CANNOT_TRIGGER); throw new BusinessException(ResponseCode.SCHEDULE_JOB_DISABLED_CANNOT_TRIGGER);
} }
try { try {
scheduler.triggerJob(getJobKey(jobId)); scheduler.triggerJob(getJobKey(jobId));
log.info("立即触发任务jobId={}, jobName={}", jobId, job.getJobName()); log.info("立即触发任务jobId={}, jobName={}", jobId, job.getJobName());
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("触发任务失败jobId={}, jobName={}", jobId, job.getJobName(), e); log.error("触发任务失败jobId={}, jobName={}", jobId, job.getJobName(), e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_TRIGGER_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_TRIGGER_FAILED);
@ -307,27 +345,27 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
try { try {
TriggerKey triggerKey = getTriggerKey(jobId); TriggerKey triggerKey = getTriggerKey(jobId);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) { if (trigger == null) {
throw new BusinessException(ResponseCode.SCHEDULE_JOB_TRIGGER_NOT_FOUND); throw new BusinessException(ResponseCode.SCHEDULE_JOB_TRIGGER_NOT_FOUND);
} }
// 创建新的Trigger // 创建新的Trigger
CronTrigger newTrigger = trigger.getTriggerBuilder() CronTrigger newTrigger = trigger.getTriggerBuilder()
.withIdentity(triggerKey) .withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build(); .build();
// 重新调度 // 重新调度
scheduler.rescheduleJob(triggerKey, newTrigger); scheduler.rescheduleJob(triggerKey, newTrigger);
// 更新数据库 // 更新数据库
ScheduleJob job = findEntityById(jobId); ScheduleJob job = findEntityById(jobId);
job.setCronExpression(cronExpression); job.setCronExpression(cronExpression);
jobRepository.save(job); jobRepository.save(job);
log.info("更新任务Cron表达式成功jobId={}, cron={}", jobId, cronExpression); log.info("更新任务Cron表达式成功jobId={}, cron={}", jobId, cronExpression);
} catch (SchedulerException e) { } catch (SchedulerException e) {
log.error("更新任务Cron表达式失败jobId={}", jobId, e); log.error("更新任务Cron表达式失败jobId={}", jobId, e);
throw new BusinessException(ResponseCode.SCHEDULE_JOB_UPDATE_CRON_FAILED); throw new BusinessException(ResponseCode.SCHEDULE_JOB_UPDATE_CRON_FAILED);
@ -337,9 +375,9 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
@Override @Override
public void loadAllEnabledJobs() { public void loadAllEnabledJobs() {
log.info("开始加载所有启用的定时任务..."); log.info("开始加载所有启用的定时任务...");
List<ScheduleJob> enabledJobs = jobRepository.findByStatusAndDeletedFalse(ScheduleJobStatusEnum.ENABLED); List<ScheduleJob> enabledJobs = jobRepository.findByStatusAndDeletedFalse(ScheduleJobStatusEnum.ENABLED);
for (ScheduleJob job : enabledJobs) { for (ScheduleJob job : enabledJobs) {
try { try {
startJob(job.getId()); startJob(job.getId());
@ -348,7 +386,7 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
log.error("加载任务失败jobId={}, jobName={}", job.getId(), job.getJobName(), e); log.error("加载任务失败jobId={}, jobName={}", job.getId(), job.getJobName(), e);
} }
} }
log.info("定时任务加载完成,成功加载 {} 个任务", enabledJobs.size()); log.info("定时任务加载完成,成功加载 {} 个任务", enabledJobs.size());
} }
@ -359,63 +397,63 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
long enabled = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.ENABLED); long enabled = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.ENABLED);
long disabled = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.DISABLED); long disabled = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.DISABLED);
long paused = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.PAUSED); long paused = jobRepository.countByStatusAndDeletedFalse(ScheduleJobStatusEnum.PAUSED);
// 2. 获取正在执行的任务从Redis // 2. 获取正在执行的任务从Redis
List<JobDashboardDTO.RunningJobDTO> runningJobs = new ArrayList<>(); List<JobDashboardDTO.RunningJobDTO> runningJobs = new ArrayList<>();
List<ScheduleJob> allJobs = jobRepository.findAll(); List<ScheduleJob> allJobs = jobRepository.findAll();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
for (ScheduleJob job : allJobs) { for (ScheduleJob job : allJobs) {
// 使用 JobStatusRedisService 读取 Hash 类型的状态数据 // 使用 JobStatusRedisService 读取 Hash 类型的状态数据
JobStatusDTO statusDTO = jobStatusRedisService.getJobStatus(job.getId()); JobStatusDTO statusDTO = jobStatusRedisService.getJobStatus(job.getId());
if (statusDTO != null && "RUNNING".equals(statusDTO.getStatus())) { if (statusDTO != null && "RUNNING".equals(statusDTO.getStatus())) {
JobDashboardDTO.RunningJobDTO runningJob = JobDashboardDTO.RunningJobDTO.builder() JobDashboardDTO.RunningJobDTO runningJob = JobDashboardDTO.RunningJobDTO.builder()
.jobId(job.getId()) .jobId(job.getId())
.jobName(job.getJobName()) .jobName(job.getJobName())
.startTime(statusDTO.getStartTime() != null ? .startTime(statusDTO.getStartTime() != null ?
statusDTO.getStartTime().format(formatter) : null) statusDTO.getStartTime().format(formatter) : null)
.progress(statusDTO.getProgress()) .progress(statusDTO.getProgress())
.message(statusDTO.getMessage()) .message(statusDTO.getMessage())
.status(statusDTO.getStatus()) .status(statusDTO.getStatus())
.build(); .build();
runningJobs.add(runningJob); runningJobs.add(runningJob);
} }
} }
// 3. 获取最近10条执行日志 // 3. 获取最近10条执行日志
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "executeTime")); PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "executeTime"));
Page<ScheduleJobLog> logPage = jobLogRepository.findAll(pageRequest); Page<ScheduleJobLog> logPage = jobLogRepository.findAll(pageRequest);
List<ScheduleJobLogDTO> recentLogs = logPage.getContent().stream() List<ScheduleJobLogDTO> recentLogs = logPage.getContent().stream()
.map(log -> { .map(log -> {
ScheduleJobLogDTO dto = new ScheduleJobLogDTO(); ScheduleJobLogDTO dto = new ScheduleJobLogDTO();
dto.setId(log.getId()); dto.setId(log.getId());
dto.setJobId(log.getJobId()); dto.setJobId(log.getJobId());
dto.setJobName(log.getJobName()); dto.setJobName(log.getJobName());
dto.setExecuteTime(log.getExecuteTime()); dto.setExecuteTime(log.getExecuteTime());
dto.setFinishTime(log.getFinishTime()); dto.setFinishTime(log.getFinishTime());
dto.setStatus(log.getStatus()); dto.setStatus(log.getStatus());
dto.setResultMessage(log.getResultMessage()); dto.setResultMessage(log.getResultMessage());
dto.setExceptionInfo(log.getExceptionInfo()); dto.setExceptionInfo(log.getExceptionInfo());
return dto; return dto;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
// 4. 构建返回结果 // 4. 构建返回结果
JobDashboardDTO.JobSummaryDTO summary = JobDashboardDTO.JobSummaryDTO.builder() JobDashboardDTO.JobSummaryDTO summary = JobDashboardDTO.JobSummaryDTO.builder()
.total(total) .total(total)
.enabled(enabled) .enabled(enabled)
.disabled(disabled) .disabled(disabled)
.paused(paused) .paused(paused)
.running((long) runningJobs.size()) .running((long) runningJobs.size())
.build(); .build();
return JobDashboardDTO.builder() return JobDashboardDTO.builder()
.summary(summary) .summary(summary)
.runningJobs(runningJobs) .runningJobs(runningJobs)
.recentLogs(recentLogs) .recentLogs(recentLogs)
.build(); .build();
} }
/** /**