Job 代码的初始化

This commit is contained in:
YunaiV
2021-02-14 11:03:13 +08:00
parent f38aada29c
commit efbd8cad49
28 changed files with 578 additions and 462 deletions

View File

@ -0,0 +1,99 @@
package cn.iocoder.dashboard.modules.infra.controller.job;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.*;
import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "定时任务")
@RestController
@RequestMapping("/infra/job")
@Validated
public class InfJobController {
@Resource
private InfJobService jobService;
@PostMapping("/create")
@ApiOperation("创建定时任务")
@PreAuthorize("@ss.hasPermission('infra:job:create')")
public CommonResult<Long> createJob(@Valid @RequestBody InfJobCreateReqVO createReqVO) {
return success(jobService.createJob(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新定时任务")
@PreAuthorize("@ss.hasPermission('infra:job:update')")
public CommonResult<Boolean> updateJob(@Valid @RequestBody InfJobUpdateReqVO updateReqVO) {
jobService.updateJob(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除定时任务")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
public CommonResult<Boolean> deleteJob(@RequestParam("id") Long id) {
jobService.deleteJob(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得定时任务")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<InfJobRespVO> getJob(@RequestParam("id") Long id) {
InfJobDO job = jobService.getJob(id);
return success(InfJobConvert.INSTANCE.convert(job));
}
@GetMapping("/list")
@ApiOperation("获得定时任务列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<List<InfJobRespVO>> getJobList(@RequestParam("ids") Collection<Long> ids) {
List<InfJobDO> list = jobService.getJobList(ids);
return success(InfJobConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得定时任务分页")
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<PageResult<InfJobRespVO>> getJobPage(@Valid InfJobPageReqVO pageVO) {
PageResult<InfJobDO> pageResult = jobService.getJobPage(pageVO);
return success(InfJobConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出定时任务 Excel")
@PreAuthorize("@ss.hasPermission('infra:job:export')")
@OperateLog(type = EXPORT)
public void exportJobExcel(@Valid InfJobExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<InfJobDO> list = jobService.getJobList(exportReqVO);
// 导出 Excel
List<InfJobExcelVO> datas = InfJobConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "定时任务.xls", "数据", InfJobExcelVO.class, datas);
}
}

View File

@ -0,0 +1,57 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 定时任务 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class InfJobBaseVO {
@ApiModelProperty(value = "任务名称", required = true, example = "测试任务")
@NotNull(message = "任务名称不能为空")
private String name;
@ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 InfJobStatusEnum 枚举")
@NotNull(message = "任务状态不能为空")
private Integer status;
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "处理器的参数", example = "yudao")
private String handlerParam;
@ApiModelProperty(value = "CRON 表达式", required = true, example = "0/10 * * * * ? *")
@NotNull(message = "CRON 表达式不能为空")
private String cronExpression;
@ApiModelProperty(value = "最后一次执行的开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date executeBeginTime;
@ApiModelProperty(value = "最后一次执行的结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date executeEndTime;
@ApiModelProperty(value = "上一次触发时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date firePrevTime;
@ApiModelProperty(value = "下一次触发时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date fireNextTime;
@ApiModelProperty(value = "监控超时时间", example = "1000")
private Integer monitorTimeout;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("定时任务创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobCreateReqVO extends InfJobBaseVO {
}

View File

@ -0,0 +1,57 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.INF_JOB_STATUS;
/**
* 定时任务 Excel VO
*
* @author 芋道源码
*/
@Data
public class InfJobExcelVO {
@ExcelProperty("任务编号")
private Long id;
@ExcelProperty("任务名称")
private String name;
@ExcelProperty(value = "任务状态", converter = DictConvert.class)
@DictFormat(INF_JOB_STATUS)
private Integer status;
@ExcelProperty("处理器的名字")
private String handlerName;
@ExcelProperty("处理器的参数")
private String handlerParam;
@ExcelProperty("CRON 表达式")
private String cronExpression;
@ExcelProperty("最后一次执行的开始时间")
private Date executeBeginTime;
@ExcelProperty("最后一次执行的结束时间")
private Date executeEndTime;
@ExcelProperty("上一次触发时间")
private Date firePrevTime;
@ExcelProperty("下一次触发时间")
private Date fireNextTime;
@ExcelProperty("监控超时时间")
private Integer monitorTimeout;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "定时任务 Excel 导出 Request VO", description = "参数和 InfJobPageReqVO 是一致的")
@Data
public class InfJobExportReqVO {
@ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配")
private String name;
@ApiModelProperty(value = "任务状态", example = "1", notes = "参见 InfJobStatusEnum 枚举")
private Integer status;
@ApiModelProperty(value = "处理器的名字", example = "sysUserSessionTimeoutJob", notes = "模糊匹配")
private String handlerName;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import cn.iocoder.dashboard.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("定时任务分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobPageReqVO extends PageParam {
@ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配")
private String name;
@ApiModelProperty(value = "任务状态", example = "1", notes = "参见 InfJobStatusEnum 枚举")
private Integer status;
@ApiModelProperty(value = "处理器的名字", example = "sysUserSessionTimeoutJob", notes = "模糊匹配")
private String handlerName;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("定时任务 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobRespVO extends InfJobBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("定时任务更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobUpdateReqVO extends InfJobBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
@NotNull(message = "任务编号不能为空")
private Long id;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.dashboard.modules.infra.convert.job;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExcelVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobRespVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 定时任务 Convert
*
* @author 芋道源码
*/
@Mapper
public interface InfJobConvert {
InfJobConvert INSTANCE = Mappers.getMapper(InfJobConvert.class);
InfJobDO convert(InfJobCreateReqVO bean);
InfJobDO convert(InfJobUpdateReqVO bean);
InfJobRespVO convert(InfJobDO bean);
List<InfJobRespVO> convertList(List<InfJobDO> list);
PageResult<InfJobRespVO> convertPage(PageResult<InfJobDO> page);
List<InfJobExcelVO> convertList02(List<InfJobDO> list);
}

View File

@ -2,6 +2,8 @@ package cn.iocoder.dashboard.modules.infra.dal.dataobject.job;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -43,6 +45,7 @@ public class InfJobDO extends BaseDO {
/**
* 处理器的参数
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String handlerParam;
// ========== 时间相关字段 ==========
@ -75,13 +78,12 @@ public class InfJobDO extends BaseDO {
private Date fireNextTime;
// ========== 监控相关字段 ==========
/**
* 监控开关
*/
private Boolean monitorSwitch;
/**
* 监控超时时间,单位:毫秒
*
* 注意,这里的超时的目的,不是进行任务的取消,而是告警任务的执行时间过长
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Integer monitorTimeout;
// TODO misfirePolicy

View File

@ -0,0 +1,37 @@
package cn.iocoder.dashboard.modules.infra.dal.mysql.job;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 定时任务 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfJobMapper extends BaseMapperX<InfJobDO> {
default PageResult<InfJobDO> selectPage(InfJobPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<InfJobDO>()
.likeIfPresent("name", reqVO.getName())
.eqIfPresent("status", reqVO.getStatus())
.likeIfPresent("handler_name", reqVO.getHandlerName())
);
}
default List<InfJobDO> selectList(InfJobExportReqVO reqVO) {
return selectList(new QueryWrapperX<InfJobDO>()
.likeIfPresent("name", reqVO.getName())
.eqIfPresent("status", reqVO.getStatus())
.likeIfPresent("handler_name", reqVO.getHandlerName())
);
}
}

View File

@ -1 +0,0 @@
package cn.iocoder.dashboard.modules.infra.dal.mysql;

View File

@ -15,4 +15,7 @@ public interface InfErrorCodeConstants {
ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1001000003, "不能删除类型为系统内置的参数配置");
ErrorCode CONFIG_GET_VALUE_ERROR_IF_SENSITIVE = new ErrorCode(1001000004, "不允许获取敏感配置到前端");
// ========== 定时任务 1001001000 ==========
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");
}

View File

@ -0,0 +1,75 @@
package cn.iocoder.dashboard.modules.infra.service.job;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 定时任务 Service 接口
*
* @author 芋道源码
*/
public interface InfJobService {
/**
* 创建定时任务
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createJob(@Valid InfJobCreateReqVO createReqVO);
/**
* 更新定时任务
*
* @param updateReqVO 更新信息
*/
void updateJob(@Valid InfJobUpdateReqVO updateReqVO);
/**
* 删除定时任务
*
* @param id 编号
*/
void deleteJob(Long id);
/**
* 获得定时任务
*
* @param id 编号
* @return 定时任务
*/
InfJobDO getJob(Long id);
/**
* 获得定时任务列表
*
* @param ids 编号
* @return 定时任务列表
*/
List<InfJobDO> getJobList(Collection<Long> ids);
/**
* 获得定时任务分页
*
* @param pageReqVO 分页查询
* @return 定时任务分页
*/
PageResult<InfJobDO> getJobPage(InfJobPageReqVO pageReqVO);
/**
* 获得定时任务列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 定时任务分页
*/
List<InfJobDO> getJobList(InfJobExportReqVO exportReqVO);
}

View File

@ -0,0 +1,86 @@
package cn.iocoder.dashboard.modules.infra.service.job.impl;
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper;
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_NOT_EXISTS;
/**
* 定时任务 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class InfJobServiceImpl implements InfJobService {
@Resource
private InfJobMapper jobMapper;
@Override
public Long createJob(InfJobCreateReqVO createReqVO) {
// 插入
InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
jobMapper.insert(job);
// 返回
return job.getId();
}
@Override
public void updateJob(InfJobUpdateReqVO updateReqVO) {
// 校验存在
this.validateJobExists(updateReqVO.getId());
// 更新
InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO);
jobMapper.updateById(updateObj);
}
@Override
public void deleteJob(Long id) {
// 校验存在
this.validateJobExists(id);
// 更新
jobMapper.deleteById(id);
}
private void validateJobExists(Long id) {
if (jobMapper.selectById(id) == null) {
throw ServiceExceptionUtil.exception(JOB_NOT_EXISTS);
}
}
@Override
public InfJobDO getJob(Long id) {
return jobMapper.selectById(id);
}
@Override
public List<InfJobDO> getJobList(Collection<Long> ids) {
return jobMapper.selectBatchIds(ids);
}
@Override
public PageResult<InfJobDO> getJobPage(InfJobPageReqVO pageReqVO) {
return jobMapper.selectPage(pageReqVO);
}
@Override
public List<InfJobDO> getJobList(InfJobExportReqVO exportReqVO) {
return jobMapper.selectList(exportReqVO);
}
}

View File

@ -1 +0,0 @@
package cn.iocoder.dashboard.modules.infra.service;

View File

@ -18,6 +18,7 @@ public enum SysDictTypeEnum {
SYS_BOOLEAN_STRING("sys_boolean_string"), // Boolean 是否类型
INF_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"), // Redis 超时类型
INF_JOB_STATUS("inf_job_status") // 任务状态的枚举
;