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

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

@ -46,7 +46,7 @@ import java.util.stream.Collectors;
@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);
} }
@ -95,7 +95,7 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 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. 强制保持原状态防止前端传入
@ -116,9 +116,9 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 重新创建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,9 +129,9 @@ 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);
@ -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,9 +199,9 @@ 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);
@ -218,6 +219,7 @@ 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));
@ -236,6 +238,7 @@ 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));
@ -254,6 +257,7 @@ 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);
@ -283,6 +287,40 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
} }
} }
@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) {
// 检查任务状态 // 检查任务状态
@ -314,9 +352,9 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
// 创建新的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);
@ -372,14 +410,14 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
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);
} }
} }
@ -388,34 +426,34 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
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();
} }
/** /**