diff --git a/src/main/java/com/xiang/common/enums/ScheduleEnums.java b/src/main/java/com/xiang/common/enums/ScheduleEnums.java new file mode 100644 index 0000000..7fa8e0e --- /dev/null +++ b/src/main/java/com/xiang/common/enums/ScheduleEnums.java @@ -0,0 +1,17 @@ +package com.xiang.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ScheduleEnums { + + DOMAIN_DYNAMIC_ANALYSIS_TASK(4, "domain", "domainDynamicAnalysisTask"), + + ; + + private final Integer modeleCode; + private final String module; + private final String taskName; +} diff --git a/src/main/java/com/xiang/common/factory/schedule/BaseScheduleTaskTemplate.java b/src/main/java/com/xiang/common/factory/schedule/BaseScheduleTaskTemplate.java new file mode 100644 index 0000000..1ce762c --- /dev/null +++ b/src/main/java/com/xiang/common/factory/schedule/BaseScheduleTaskTemplate.java @@ -0,0 +1,144 @@ +package com.xiang.common.factory.schedule; + +import com.xiang.common.pojo.schedule.ScheduleOpeningConfigDO; +import com.xiang.common.pojo.schedule.TaskResult; +import com.xiang.common.pojo.schedule.ValidationResult; +import com.xiang.common.service.IScheduleOpeningConfigService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +public abstract class BaseScheduleTaskTemplate { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private final IScheduleOpeningConfigService scheduleOpeningConfigService; + + protected BaseScheduleTaskTemplate(IScheduleOpeningConfigService scheduleOpeningConfigService) { + this.scheduleOpeningConfigService = scheduleOpeningConfigService; + } + + + /** + * 模板方法 - 定义任务执行的标准流程 + * 子类不应覆写此方法 + */ + public final void run() { + String taskName = getTaskName(); + Integer module = getModule(); + LocalDateTime startTime = LocalDateTime.now(); + logger.info("【{}】任务开始执行,开始时间:{}", taskName, startTime.format(formatter)); + + try { + // 1. 参数校验 + logger.info("【{}】开始参数校验...", taskName); + ValidationResult validate = validate(module, taskName); + + if (!validate.isValid()) { + logger.error("【{}】参数校验失败:{}", taskName, validate.getMessage()); + onValidationFailure(validate); + return; + } + logger.info("【{}】参数校验通过", taskName); + + // 2. 执行业务逻辑 + logger.info("【{}】开始执行业务逻辑...", taskName); + TaskResult result = doExecute(validate.getValidatedParams()); + + // 3. 记录成功结果 + recordSuccess(result, startTime); + } catch (Exception e) { + // 4. 记录失败结果 + logger.error("【{}】任务执行异常", taskName, e); + recordFailure(e, startTime); + } + + LocalDateTime endTime = LocalDateTime.now(); + logger.info("【{}】任务结束,结束时间:{}", taskName, endTime.format(formatter)); + } + + /** + * 获取任务名称(子类必须实现) + */ + protected abstract String getTaskName(); + + /** + * 获取模块名称(子类必须实现) + * @return + */ + protected abstract Integer getModule(); + + /** + * 任务校验(子类必须实现) + * @return 校验结果,包含是否通过、错误信息、校验通过的参数对象 + */ + private ValidationResult validate(Integer moduleCode, String taskName) { + ValidationResult validationResult = new ValidationResult(); + boolean flag = checkTaskOpening(moduleCode, taskName); + validationResult.setValidatedParams(null); + validationResult.setValid(flag); + validationResult.setMessage(flag ? "" : "任务未开启"); + return validationResult; + } + + /** + * 校验任务是否开启 + * @param moduleCode 模块id + * @param taskName 任务名称 + * @return + */ + private boolean checkTaskOpening(Integer moduleCode, String taskName) { + ScheduleOpeningConfigDO configsByModule = scheduleOpeningConfigService.getConfigByModule(moduleCode, taskName); + if (Objects.isNull(configsByModule)) { + return false; + } + return Objects.equals(configsByModule.getStatus(), 1); + } + + /** + * 具体的业务逻辑执行(子类必须实现) + * @param validatedParams 校验通过的参数 + * @return 任务执行结果 + */ + protected abstract TaskResult doExecute(Object validatedParams); + + /** + * 记录成功结果 - 子类可选择性覆写 + */ + protected void recordSuccess(TaskResult result, LocalDateTime startTime) { + LocalDateTime endTime = LocalDateTime.now(); + long duration = java.time.Duration.between(startTime, endTime).toMillis(); + + logger.info("【{}】任务执行成功,耗时:{}ms,结果概要:{}", + getTaskName(), duration, result.getSummary()); + + // 可在此扩展:写入数据库、发送通知等 + // 例如:saveTaskLog(getTaskName(), "SUCCESS", duration, result.getDetail()); + } + + /** + * 记录失败结果 - 子类可选择性覆写 + */ + protected void recordFailure(Exception e, LocalDateTime startTime) { + LocalDateTime endTime = LocalDateTime.now(); + long duration = java.time.Duration.between(startTime, endTime).toMillis(); + + logger.error("【{}】任务执行失败,耗时:{}ms,错误:{}", + getTaskName(), duration, e.getMessage()); + + // 可在此扩展:写入数据库、发送告警等 + // 例如:saveTaskLog(getTaskName(), "FAILURE", duration, e.getMessage()); + } + + /** + * 参数校验失败时的处理 - 子类可选择性覆写 + */ + protected void onValidationFailure(ValidationResult result) { + // 默认实现:仅记录日志 + logger.warn("【{}】参数校验失败,跳过任务执行", getTaskName()); + // 可在此扩展:发送通知、写入失败日志等 + } +} diff --git a/src/main/java/com/xiang/common/mapper/ScheduleOpeningConfigDao.java b/src/main/java/com/xiang/common/mapper/ScheduleOpeningConfigDao.java new file mode 100644 index 0000000..a574486 --- /dev/null +++ b/src/main/java/com/xiang/common/mapper/ScheduleOpeningConfigDao.java @@ -0,0 +1,11 @@ +package com.xiang.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.xiang.common.pojo.schedule.ScheduleOpeningConfigDO; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Mapper +@Repository +public interface ScheduleOpeningConfigDao extends BaseMapper { +} diff --git a/src/main/java/com/xiang/common/pojo/schedule/ScheduleOpeningConfigDO.java b/src/main/java/com/xiang/common/pojo/schedule/ScheduleOpeningConfigDO.java new file mode 100644 index 0000000..a025864 --- /dev/null +++ b/src/main/java/com/xiang/common/pojo/schedule/ScheduleOpeningConfigDO.java @@ -0,0 +1,24 @@ +package com.xiang.common.pojo.schedule; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("schedule_opening_config") +public class ScheduleOpeningConfigDO { + private Long id; + /** + * 模块id(0:glados 1:芬玩岛 2:江体小程序 3:江体zlb 4:ddns) + */ + private Integer module; + private String beanName; + private Integer status; + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/xiang/common/pojo/schedule/TaskResult.java b/src/main/java/com/xiang/common/pojo/schedule/TaskResult.java new file mode 100644 index 0000000..e603973 --- /dev/null +++ b/src/main/java/com/xiang/common/pojo/schedule/TaskResult.java @@ -0,0 +1,17 @@ +package com.xiang.common.pojo.schedule; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TaskResult { + /** + * 是否成功 + */ + private boolean success; + private String summary; + private Object detail; +} diff --git a/src/main/java/com/xiang/common/pojo/schedule/ValidationResult.java b/src/main/java/com/xiang/common/pojo/schedule/ValidationResult.java new file mode 100644 index 0000000..d3a919b --- /dev/null +++ b/src/main/java/com/xiang/common/pojo/schedule/ValidationResult.java @@ -0,0 +1,15 @@ +package com.xiang.common.pojo.schedule; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.checkerframework.checker.units.qual.A; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ValidationResult { + private boolean valid; + private String message; + private Object validatedParams; +} diff --git a/src/main/java/com/xiang/common/service/IScheduleOpeningConfigService.java b/src/main/java/com/xiang/common/service/IScheduleOpeningConfigService.java new file mode 100644 index 0000000..597bd24 --- /dev/null +++ b/src/main/java/com/xiang/common/service/IScheduleOpeningConfigService.java @@ -0,0 +1,17 @@ +package com.xiang.common.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.xiang.common.pojo.schedule.ScheduleOpeningConfigDO; + +import java.util.List; + +public interface IScheduleOpeningConfigService extends IService { + + /** + * 根据模块id和任务名称查询 + * @param moduleCode + * @param taskName + * @return + */ + ScheduleOpeningConfigDO getConfigByModule(Integer moduleCode, String taskName); +} diff --git a/src/main/java/com/xiang/common/service/ScheduleOpeningConfigServiceImpl.java b/src/main/java/com/xiang/common/service/ScheduleOpeningConfigServiceImpl.java new file mode 100644 index 0000000..69816e3 --- /dev/null +++ b/src/main/java/com/xiang/common/service/ScheduleOpeningConfigServiceImpl.java @@ -0,0 +1,20 @@ +package com.xiang.common.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xiang.common.mapper.ScheduleOpeningConfigDao; +import com.xiang.common.pojo.schedule.ScheduleOpeningConfigDO; +import org.springframework.stereotype.Service; + + +@Service +public class ScheduleOpeningConfigServiceImpl extends ServiceImpl implements IScheduleOpeningConfigService { + @Override + public ScheduleOpeningConfigDO getConfigByModule(Integer moduleCode, String taskName) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(ScheduleOpeningConfigDO::getModule, moduleCode); + lqw.eq(ScheduleOpeningConfigDO::getBeanName, taskName); + return baseMapper.selectOne(lqw); + } +} diff --git a/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTask.java b/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTask.java index 521e3d7..a5116ea 100644 --- a/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTask.java +++ b/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTask.java @@ -1,20 +1,39 @@ package com.xiang.service.module.domain.schedule; +import com.xiang.common.enums.ScheduleEnums; +import com.xiang.common.factory.schedule.BaseScheduleTaskTemplate; +import com.xiang.common.pojo.schedule.TaskResult; +import com.xiang.common.service.IScheduleOpeningConfigService; import com.xiang.common.utils.IpUtils; import com.xiang.service.module.domain.service.IDomainService; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; @Slf4j -@RequiredArgsConstructor -public class DomainDynamicAnalysisTask { +@Component +public class DomainDynamicAnalysisTask extends BaseScheduleTaskTemplate { private final IDomainService IDomainService; - @Scheduled(cron = "0 0/30 * * * ? ") - public void dynamicDomainSchedule() { + public DomainDynamicAnalysisTask(IScheduleOpeningConfigService scheduleOpeningConfigService, IDomainService IDomainService) { + super(scheduleOpeningConfigService); + this.IDomainService = IDomainService; + } + + @Override + protected Integer getModule() { + return ScheduleEnums.DOMAIN_DYNAMIC_ANALYSIS_TASK.getModeleCode(); + } + + @Override + protected String getTaskName() { + return ScheduleEnums.DOMAIN_DYNAMIC_ANALYSIS_TASK.getTaskName(); + } + + @Override + protected TaskResult doExecute(Object validatedParams) { String publicIp = ""; + TaskResult taskResult = new TaskResult(); try { publicIp = IpUtils.getPublicIp(); } catch (Exception e) { @@ -27,5 +46,10 @@ public class DomainDynamicAnalysisTask { log.error("动态解析公网ip失败, ip:{}", publicIp, e); } } + taskResult.setSuccess(true); + taskResult.setSummary(""); + taskResult.setDetail(null); + return taskResult; } + } diff --git a/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTaskConfig.java b/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTaskConfig.java new file mode 100644 index 0000000..4bc12be --- /dev/null +++ b/src/main/java/com/xiang/service/module/domain/schedule/DomainDynamicAnalysisTaskConfig.java @@ -0,0 +1,23 @@ +package com.xiang.service.module.domain.schedule; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@Component +@Slf4j +@RequiredArgsConstructor +@RestController +public class DomainDynamicAnalysisTaskConfig { + + private final DomainDynamicAnalysisTask domainDynamicAnalysisTask; + + @Scheduled(cron = "0 0/30 * * * ? ") + @GetMapping("/test") + public void dynamicDomainSchedule() { + domainDynamicAnalysisTask.run(); + } +}