增加计划飞行
This commit is contained in:
parent
3162f12835
commit
4ce9541397
|
|
@ -65,7 +65,7 @@ public class MediaFileController {
|
||||||
})
|
})
|
||||||
@DataFilter(tableAlias = "t")
|
@DataFilter(tableAlias = "t")
|
||||||
@RequiresPermissions("bus:media:album")
|
@RequiresPermissions("bus:media:album")
|
||||||
public Result<PageData<MediaFileDTO>> getHangarAlbum(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
public Result<PageData<MediaFileDTO>> getAlbum(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
PageData<MediaFileDTO> page = mediaFileService.getAlbum(params);
|
PageData<MediaFileDTO> page = mediaFileService.getAlbum(params);
|
||||||
|
|
||||||
return new Result<PageData<MediaFileDTO>>().ok(page);
|
return new Result<PageData<MediaFileDTO>>().ok(page);
|
||||||
|
|
@ -97,7 +97,7 @@ public class MediaFileController {
|
||||||
@GetMapping("/conditionDownloadMedia")
|
@GetMapping("/conditionDownloadMedia")
|
||||||
@RequiresPermissions("bus:media:download")
|
@RequiresPermissions("bus:media:download")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = "hangarSn", description = "机库sn"),
|
@Parameter(name = "dockSn", description = "机库sn"),
|
||||||
@Parameter(name = "routeId", description = "航线标识"),
|
@Parameter(name = "routeId", description = "航线标识"),
|
||||||
@Parameter(name = "startTime", description = "开始时间"),
|
@Parameter(name = "startTime", description = "开始时间"),
|
||||||
@Parameter(name = "endTime", description = "结束时间")
|
@Parameter(name = "endTime", description = "结束时间")
|
||||||
|
|
@ -113,7 +113,7 @@ public class MediaFileController {
|
||||||
@GetMapping("/oneClickGetDownloadPath")
|
@GetMapping("/oneClickGetDownloadPath")
|
||||||
@RequiresPermissions("bus:media:download")
|
@RequiresPermissions("bus:media:download")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = "hangarSn", description = "机库sn"),
|
@Parameter(name = "dockSn", description = "机库sn"),
|
||||||
@Parameter(name = "routeId", description = "航线标识"),
|
@Parameter(name = "routeId", description = "航线标识"),
|
||||||
@Parameter(name = "startTime", description = "开始时间"),
|
@Parameter(name = "startTime", description = "开始时间"),
|
||||||
@Parameter(name = "endTime", description = "结束时间")
|
@Parameter(name = "endTime", description = "结束时间")
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class RouteFlightController {
|
||||||
public Result<Object> flightExecute(@PathVariable String dockSn,
|
public Result<Object> flightExecute(@PathVariable String dockSn,
|
||||||
@RequestBody FlightExecute flightExecute) {
|
@RequestBody FlightExecute flightExecute) {
|
||||||
|
|
||||||
return new Result<>().ok(routeFlightService.flightExecute(dockSn, flightExecute));
|
return new Result<>().ok(routeFlightService.flightExecute(dockSn, flightExecute, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@LogOperation("空中下发航线")
|
@LogOperation("空中下发航线")
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ public interface FlightTaskService extends CrudService<FlightTaskEntity, FlightT
|
||||||
|
|
||||||
void addTakeoffTask(String taskId, String dockSn);//一键起飞任务
|
void addTakeoffTask(String taskId, String dockSn);//一键起飞任务
|
||||||
|
|
||||||
|
void addJobRouteTask(String taskId, Long jobId);//计划飞行任务
|
||||||
|
|
||||||
//更新架次完成信息
|
//更新架次完成信息
|
||||||
void updateTaskComplete(String dockSn);
|
void updateTaskComplete(String dockSn);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ public interface RouteFlightService {
|
||||||
String flightTaskUndo(String dockSn, List<String> taskIds);
|
String flightTaskUndo(String dockSn, List<String> taskIds);
|
||||||
|
|
||||||
//执行航线
|
//执行航线
|
||||||
String flightExecute(String dockSn, FlightExecute flightExecute);
|
String flightExecute(String dockSn, FlightExecute flightExecute, Boolean isRecord);
|
||||||
|
|
||||||
//空中下发航线
|
//空中下发航线
|
||||||
String inFlightWaylineDeliver(String dockSn, Long routeId);
|
String inFlightWaylineDeliver(String dockSn, Long routeId);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,12 @@ import com.multictrl.modules.business.dto.RouteDTO;
|
||||||
import com.multictrl.modules.business.entity.*;
|
import com.multictrl.modules.business.entity.*;
|
||||||
import com.multictrl.modules.business.influxdb.UavReport;
|
import com.multictrl.modules.business.influxdb.UavReport;
|
||||||
import com.multictrl.modules.business.service.*;
|
import com.multictrl.modules.business.service.*;
|
||||||
|
import com.multictrl.modules.job.dao.ScheduleJobDao;
|
||||||
|
import com.multictrl.modules.job.dto.ScheduleJobDTO;
|
||||||
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
import com.multictrl.modules.security.user.SecurityUser;
|
import com.multictrl.modules.security.user.SecurityUser;
|
||||||
|
import com.multictrl.modules.sys.dto.SysUserDTO;
|
||||||
|
import com.multictrl.modules.sys.service.SysUserService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
@ -43,6 +48,8 @@ public class FlightTaskServiceImpl extends CrudServiceImpl<FlightTaskDao, Flight
|
||||||
private final MediaFileService mediaFileService;
|
private final MediaFileService mediaFileService;
|
||||||
private final DockDeviceDao dockDeviceDao;
|
private final DockDeviceDao dockDeviceDao;
|
||||||
private final SrsService srsService;
|
private final SrsService srsService;
|
||||||
|
private final ScheduleJobDao scheduleJobDao;
|
||||||
|
private final SysUserService userService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryWrapper<FlightTaskEntity> getWrapper(Map<String, Object> params) {
|
public QueryWrapper<FlightTaskEntity> getWrapper(Map<String, Object> params) {
|
||||||
|
|
@ -111,6 +118,27 @@ public class FlightTaskServiceImpl extends CrudServiceImpl<FlightTaskDao, Flight
|
||||||
baseDao.insert(entity);
|
baseDao.insert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addJobRouteTask(String taskId, Long jobId) {
|
||||||
|
FlightTaskEntity entity = new FlightTaskEntity();
|
||||||
|
entity.setTaskId(taskId);
|
||||||
|
entity.setTaskType(3);
|
||||||
|
ScheduleJobEntity jobEntity = scheduleJobDao.getById(jobId);
|
||||||
|
addDockInfo(entity, jobEntity.getDockSn());
|
||||||
|
long routeId = Long.parseLong(jobEntity.getParams());
|
||||||
|
entity.setRouteId(routeId);
|
||||||
|
RouteDTO route = routeService.getRoute(routeId);
|
||||||
|
entity.setRouteName(route.getRouteName());
|
||||||
|
entity.setRouteType(route.getTemplateType());
|
||||||
|
entity.setRouteDistance(route.getTotalDistance());
|
||||||
|
entity.setWaypointNum(route.getRouteWaypointList().size());
|
||||||
|
entity.setDeptId(jobEntity.getDeptId());
|
||||||
|
entity.setTaskStatus(FlightTaskStatus.IN_PROGRESS.getCode());
|
||||||
|
SysUserDTO userDTO = userService.get(jobEntity.getUpdater());
|
||||||
|
entity.setCreateName(userDTO.getRealName());
|
||||||
|
baseDao.insert(entity);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTaskComplete(String dockSn) {
|
public void updateTaskComplete(String dockSn) {
|
||||||
String taskId = (String) CacheUtils.get(BusinessConstant.WORKING_TASK_ID + dockSn);
|
String taskId = (String) CacheUtils.get(BusinessConstant.WORKING_TASK_ID + dockSn);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public class RouteFlightServiceImpl implements RouteFlightService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String flightExecute(String dockSn, FlightExecute flightExecute) {
|
public String flightExecute(String dockSn, FlightExecute flightExecute, Boolean isRecord) {
|
||||||
ReentrantLock lock = cacheLock.computeIfAbsent(dockSn, k -> new ReentrantLock());
|
ReentrantLock lock = cacheLock.computeIfAbsent(dockSn, k -> new ReentrantLock());
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
|
|
@ -122,7 +122,9 @@ public class RouteFlightServiceImpl implements RouteFlightService {
|
||||||
//执行任务
|
//执行任务
|
||||||
Utils.sleep(1000);
|
Utils.sleep(1000);
|
||||||
String resultMsg = djiBaseService.executeAndReturnResult(dockSn, "flighttask_execute", new JSONObject().set("flight_id", taskId));
|
String resultMsg = djiBaseService.executeAndReturnResult(dockSn, "flighttask_execute", new JSONObject().set("flight_id", taskId));
|
||||||
flightTaskService.addRouteTask(taskId, dockSn, route.getId());
|
if (isRecord) {
|
||||||
|
flightTaskService.addRouteTask(taskId, dockSn, route.getId());
|
||||||
|
}
|
||||||
return resultMsg;
|
return resultMsg;
|
||||||
} finally {
|
} finally {
|
||||||
Utils.sleep(2000);
|
Utils.sleep(2000);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.multictrl.modules.job.controller;
|
package com.multictrl.modules.job.controller;
|
||||||
|
|
||||||
|
import com.multictrl.common.annotation.ApiOrder;
|
||||||
|
import com.multictrl.common.annotation.DataFilter;
|
||||||
import com.multictrl.common.annotation.LogOperation;
|
import com.multictrl.common.annotation.LogOperation;
|
||||||
import com.multictrl.common.constant.Constant;
|
import com.multictrl.common.constant.Constant;
|
||||||
import com.multictrl.common.page.PageData;
|
import com.multictrl.common.page.PageData;
|
||||||
|
|
@ -13,9 +15,8 @@ import com.multictrl.modules.job.service.ScheduleJobService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
|
@ -28,8 +29,9 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/sys/schedule")
|
@RequestMapping("/sys/schedule")
|
||||||
@Tag(name = "定时任务")
|
@Tag(name = "计划飞行")
|
||||||
@AllArgsConstructor
|
@ApiOrder(19)
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class ScheduleJobController {
|
public class ScheduleJobController {
|
||||||
private final ScheduleJobService scheduleJobService;
|
private final ScheduleJobService scheduleJobService;
|
||||||
|
|
||||||
|
|
@ -37,8 +39,12 @@ public class ScheduleJobController {
|
||||||
@Operation(summary = "分页")
|
@Operation(summary = "分页")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
||||||
@Parameter(name = Constant.LIMIT, description = "每页显示记录数")
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
|
||||||
|
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段"),
|
||||||
|
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
|
||||||
|
@Parameter(name = "beanName", description = "beanName")
|
||||||
})
|
})
|
||||||
|
@DataFilter(tableAlias = "s")
|
||||||
@RequiresPermissions("sys:schedule:page")
|
@RequiresPermissions("sys:schedule:page")
|
||||||
public Result<PageData<ScheduleJobDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
public Result<PageData<ScheduleJobDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
PageData<ScheduleJobDTO> page = scheduleJobService.page(params);
|
PageData<ScheduleJobDTO> page = scheduleJobService.page(params);
|
||||||
|
|
@ -57,66 +63,66 @@ public class ScheduleJobController {
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@Operation(summary = "保存")
|
@Operation(summary = "保存")
|
||||||
@LogOperation("保存")
|
@LogOperation("新增计划")
|
||||||
@RequiresPermissions("sys:schedule:save")
|
@RequiresPermissions("sys:schedule:save")
|
||||||
public Result<Object> save(@RequestBody ScheduleJobDTO dto) {
|
public Result<String> save(@RequestBody ScheduleJobDTO dto) {
|
||||||
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
|
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
|
||||||
|
|
||||||
scheduleJobService.save(dto);
|
scheduleJobService.save(dto);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
@Operation(summary = "修改")
|
@Operation(summary = "修改")
|
||||||
@LogOperation("修改")
|
@LogOperation("修改计划")
|
||||||
@RequiresPermissions("sys:schedule:update")
|
@RequiresPermissions("sys:schedule:update")
|
||||||
public Result<Object> update(@RequestBody ScheduleJobDTO dto) {
|
public Result<String> update(@RequestBody ScheduleJobDTO dto) {
|
||||||
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
|
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
|
||||||
|
|
||||||
scheduleJobService.update(dto);
|
scheduleJobService.update(dto);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
@Operation(summary = "删除")
|
@Operation(summary = "删除")
|
||||||
@LogOperation("删除")
|
@LogOperation("删除计划")
|
||||||
@RequiresPermissions("sys:schedule:delete")
|
@RequiresPermissions("sys:schedule:delete")
|
||||||
public Result<Object> delete(@RequestBody Long[] ids) {
|
public Result<String> delete(@RequestBody Long[] ids) {
|
||||||
scheduleJobService.deleteBatch(ids);
|
scheduleJobService.deleteBatch(ids);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/run")
|
@PutMapping("/run")
|
||||||
@Operation(summary = "立即执行")
|
@Operation(summary = "立即执行")
|
||||||
@LogOperation("立即执行")
|
@LogOperation("立即执行")
|
||||||
@RequiresPermissions("sys:schedule:run")
|
@RequiresPermissions("sys:schedule:run")
|
||||||
public Result<Object> run(@RequestBody Long[] ids) {
|
public Result<String> run(@RequestBody Long[] ids) {
|
||||||
scheduleJobService.run(ids);
|
scheduleJobService.run(ids);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/pause")
|
@PutMapping("/pause")
|
||||||
@Operation(summary = "暂停")
|
@Operation(summary = "暂停")
|
||||||
@LogOperation("暂停")
|
@LogOperation("暂停计划")
|
||||||
@RequiresPermissions("sys:schedule:pause")
|
@RequiresPermissions("sys:schedule:pause")
|
||||||
public Result<Object> pause(@RequestBody Long[] ids) {
|
public Result<String> pause(@RequestBody Long[] ids) {
|
||||||
scheduleJobService.pause(ids);
|
scheduleJobService.pause(ids);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/resume")
|
@PutMapping("/resume")
|
||||||
@Operation(summary = "恢复")
|
@Operation(summary = "恢复")
|
||||||
@LogOperation("恢复")
|
@LogOperation("恢复计划")
|
||||||
@RequiresPermissions("sys:schedule:resume")
|
@RequiresPermissions("sys:schedule:resume")
|
||||||
public Result<Object> resume(@RequestBody Long[] ids) {
|
public Result<String> resume(@RequestBody Long[] ids) {
|
||||||
scheduleJobService.resume(ids);
|
scheduleJobService.resume(ids);
|
||||||
|
|
||||||
return new Result<Object>();
|
return new Result<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.multictrl.modules.job.controller;
|
package com.multictrl.modules.job.controller;
|
||||||
|
|
||||||
|
import com.multictrl.common.annotation.ApiOrder;
|
||||||
|
import com.multictrl.common.annotation.DataFilter;
|
||||||
import com.multictrl.common.constant.Constant;
|
import com.multictrl.common.constant.Constant;
|
||||||
import com.multictrl.common.page.PageData;
|
import com.multictrl.common.page.PageData;
|
||||||
import com.multictrl.common.utils.Result;
|
import com.multictrl.common.utils.Result;
|
||||||
|
|
@ -10,7 +12,7 @@ import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
|
@ -23,8 +25,9 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/sys/scheduleLog")
|
@RequestMapping("/sys/scheduleLog")
|
||||||
@Tag(name = "定时任务日志")
|
@Tag(name = "计划飞行日志")
|
||||||
@AllArgsConstructor
|
@ApiOrder(20)
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class ScheduleJobLogController {
|
public class ScheduleJobLogController {
|
||||||
private final ScheduleJobLogService scheduleJobLogService;
|
private final ScheduleJobLogService scheduleJobLogService;
|
||||||
|
|
||||||
|
|
@ -32,8 +35,12 @@ public class ScheduleJobLogController {
|
||||||
@Operation(summary = "分页")
|
@Operation(summary = "分页")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
||||||
@Parameter(name = Constant.LIMIT, description = "每页显示记录数")
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
|
||||||
|
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段"),
|
||||||
|
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
|
||||||
|
@Parameter(name = "jobId", description = "jobId")
|
||||||
})
|
})
|
||||||
|
@DataFilter
|
||||||
@RequiresPermissions("sys:schedule:log")
|
@RequiresPermissions("sys:schedule:log")
|
||||||
public Result<PageData<ScheduleJobLogDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
public Result<PageData<ScheduleJobLogDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
PageData<ScheduleJobLogDTO> page = scheduleJobLogService.page(params);
|
PageData<ScheduleJobLogDTO> page = scheduleJobLogService.page(params);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package com.multictrl.modules.job.dao;
|
package com.multictrl.modules.job.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.multictrl.common.dao.BaseDao;
|
import com.multictrl.common.dao.BaseDao;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -13,9 +16,19 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ScheduleJobDao extends BaseDao<ScheduleJobEntity> {
|
public interface ScheduleJobDao extends BaseDao<ScheduleJobEntity> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新状态
|
* 批量更新状态
|
||||||
*/
|
*/
|
||||||
int updateBatch(Map<String, Object> map);
|
int updateBatch(Map<String, Object> map);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*/
|
||||||
|
IPage<ScheduleJobEntity> pageList(@Param("ipage") IPage<ScheduleJobEntity> ipage, @Param("ew") QueryWrapper<ScheduleJobEntity> ew);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询详情
|
||||||
|
*/
|
||||||
|
ScheduleJobEntity getById(@Param("id") Long id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
package com.multictrl.modules.job.dto;
|
package com.multictrl.modules.job.dto;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.multictrl.common.validator.group.AddGroup;
|
import com.multictrl.common.validator.group.AddGroup;
|
||||||
import com.multictrl.common.validator.group.DefaultGroup;
|
import com.multictrl.common.validator.group.DefaultGroup;
|
||||||
import com.multictrl.common.validator.group.UpdateGroup;
|
import com.multictrl.common.validator.group.UpdateGroup;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.AssertTrue;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Null;
|
import jakarta.validation.constraints.Null;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.validator.constraints.Range;
|
import org.hibernate.validator.constraints.Range;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务
|
* 定时任务
|
||||||
|
|
@ -27,31 +33,121 @@ public class ScheduleJobDTO implements Serializable {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Schema(title = "id")
|
@Schema(description = "id")
|
||||||
@Null(message="{id.null}", groups = AddGroup.class)
|
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||||
@NotNull(message="{id.require}", groups = UpdateGroup.class)
|
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(title = "spring bean名称")
|
@NotBlank(message = "任务名称不能为空", groups = DefaultGroup.class)
|
||||||
@NotBlank(message = "{schedule.bean.require}", groups = DefaultGroup.class)
|
@Schema(description = "任务名称")
|
||||||
private String beanName;
|
private String jobName;
|
||||||
|
|
||||||
@Schema(title = "参数")
|
@Schema(description = "任务执行类")
|
||||||
|
private String beanName = "routeTask";
|
||||||
|
|
||||||
|
@NotNull(message = "定时类型不能为空", groups = DefaultGroup.class)
|
||||||
|
@Schema(description = "定时类型 1指定时间 2每天几点 3每周周几几点 4每月几号几点")
|
||||||
|
private Integer cronType;
|
||||||
|
|
||||||
|
@Schema(description = "年")
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
@Schema(description = "月")
|
||||||
|
private Integer month;
|
||||||
|
|
||||||
|
@Schema(description = "日")
|
||||||
|
private List<Integer> day;
|
||||||
|
|
||||||
|
@Schema(description = "时")
|
||||||
|
private Integer hour;
|
||||||
|
|
||||||
|
@Schema(description = "分")
|
||||||
|
private Integer minute;
|
||||||
|
|
||||||
|
@Schema(description = "参数(航线标识)")
|
||||||
private String params;
|
private String params;
|
||||||
|
|
||||||
@Schema(title = "cron表达式")
|
@Schema(description = "任务状态 0:暂停 1:正常 -1失效")
|
||||||
@NotBlank(message = "{schedule.cron.require}", groups = DefaultGroup.class)
|
@Range(min = -1, max = 1, message = "{schedule.status.range}", groups = DefaultGroup.class)
|
||||||
private String cronExpression;
|
|
||||||
|
|
||||||
@Schema(title = "任务状态 0:暂停 1:正常")
|
|
||||||
@Range(min=0, max=1, message = "{schedule.status.range}", groups = DefaultGroup.class)
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(title = "备注")
|
@Schema(description = "备注")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
@Schema(title = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
private Date createDate;
|
private Date createDate;
|
||||||
|
|
||||||
|
@NotBlank(message = "机库sn不能为空", groups = DefaultGroup.class)
|
||||||
|
@Schema(description = "机库sn")
|
||||||
|
private String dockSn;
|
||||||
|
|
||||||
|
@Schema(description = "航线名称")
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String routeName;
|
||||||
|
|
||||||
|
@Schema(description = "机库名称")
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String dockName;
|
||||||
|
|
||||||
|
@Schema(description = "下次执行时间")
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String nextRunTime;
|
||||||
|
|
||||||
|
@Schema(description = "执行规则")
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String cronRules;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
@AssertTrue(message = "参数不能为空", groups = DefaultGroup.class)
|
||||||
|
public boolean isParamsValid() {
|
||||||
|
return !Objects.equals(beanName, "routeTask") || StrUtil.isNotBlank(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
@AssertTrue(message = "时间格式有问题", groups = DefaultGroup.class)
|
||||||
|
public boolean isCronTypeValid() {
|
||||||
|
if (cronType == null) return false;
|
||||||
|
return switch (cronType) {
|
||||||
|
case 1 -> // 指定时间(年、月、日、时、分)
|
||||||
|
year != null && month != null && !day.isEmpty() && hour != null && minute != null;
|
||||||
|
case 2 -> // 每天几点(时、分)
|
||||||
|
hour != null && minute != null;
|
||||||
|
case 3 ->// 每周周几几点(周几、时、分)
|
||||||
|
!day.isEmpty() && hour != null && minute != null && day.stream().allMatch(d -> d >= 1 && d <= 7);
|
||||||
|
case 4 ->// 每月几号几点(日、时、分)
|
||||||
|
!day.isEmpty() && hour != null && minute != null && day.stream().allMatch(d -> d >= 1 && d <= 31);
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否断点续飞
|
||||||
|
*/
|
||||||
|
@Schema(description = "是否断点续飞")
|
||||||
|
private Boolean isBreakpointFly;
|
||||||
|
/**
|
||||||
|
* 断点续飞最大时间
|
||||||
|
*/
|
||||||
|
@Schema(description = "断点续飞最大时间 HH:mm:ss")
|
||||||
|
private String breakMaxTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断点续飞最小时间
|
||||||
|
*/
|
||||||
|
@Schema(description = "断点续飞最小时间 HH:mm:ss")
|
||||||
|
private String breakMinTime;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
@AssertTrue(message = "断点续飞时间不能为空")
|
||||||
|
public boolean isBreakTimeValid() {
|
||||||
|
if (isBreakpointFly) {
|
||||||
|
return StringUtils.isNotBlank(breakMaxTime) && StringUtils.isNotBlank(breakMinTime);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,28 +19,30 @@ public class ScheduleJobLogDTO implements Serializable {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Schema(title = "id")
|
@Schema(description = "id")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(title = "任务id")
|
@Schema(description = "任务id")
|
||||||
private Long jobId;
|
private Long jobId;
|
||||||
|
|
||||||
@Schema(title = "spring bean名称")
|
/* @Schema(title = "spring bean名称")
|
||||||
private String beanName;
|
private String beanName;
|
||||||
|
|
||||||
@Schema(title = "参数")
|
@Schema(title = "参数")
|
||||||
private String params;
|
private String params;*/
|
||||||
|
|
||||||
@Schema(title = "任务状态 0:失败 1:成功")
|
@Schema(description = "任务状态 0:失败 1:成功")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(title = "失败信息")
|
@Schema(description = "失败信息")
|
||||||
private String error;
|
private String error;
|
||||||
|
|
||||||
@Schema(title = "耗时(单位:毫秒)")
|
@Schema(description = "耗时(单位:毫秒)")
|
||||||
private Integer times;
|
private Integer times;
|
||||||
|
|
||||||
@Schema(title = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private Date createDate;
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "任务名称")
|
||||||
|
private String jobName;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务
|
* 定时任务
|
||||||
|
|
@ -16,40 +17,110 @@ import java.util.Date;
|
||||||
* @author Sdy
|
* @author Sdy
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper=false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@TableName("schedule_job")
|
@TableName("schedule_job")
|
||||||
public class ScheduleJobEntity extends BaseEntity {
|
public class ScheduleJobEntity extends BaseEntity {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spring bean名称
|
* spring bean名称
|
||||||
*/
|
*/
|
||||||
private String beanName;
|
private String beanName;
|
||||||
/**
|
/**
|
||||||
* 参数
|
* 参数
|
||||||
*/
|
*/
|
||||||
private String params;
|
private String params;
|
||||||
/**
|
/**
|
||||||
* cron表达式
|
* cron表达式
|
||||||
*/
|
*/
|
||||||
private String cronExpression;
|
private String cronExpression;
|
||||||
/**
|
/**
|
||||||
* 任务状态 0:暂停 1:正常
|
* 任务状态 0:暂停 1:正常
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
/**
|
/**
|
||||||
* 备注
|
* 备注
|
||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
/**
|
/**
|
||||||
* 更新者
|
* 更新者
|
||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
private Long updater;
|
private Long updater;
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
private Date updateDate;
|
private Date updateDate;
|
||||||
|
/**
|
||||||
|
* 任务名称
|
||||||
|
*/
|
||||||
|
private String jobName;
|
||||||
|
/**
|
||||||
|
* 定时类型 1指定时间 2每天几点 3每周周几几点 4每月几号几点
|
||||||
|
*/
|
||||||
|
private Integer cronType;
|
||||||
|
/**
|
||||||
|
* 年
|
||||||
|
*/
|
||||||
|
private Integer year;
|
||||||
|
/**
|
||||||
|
* 月
|
||||||
|
*/
|
||||||
|
private Integer month;
|
||||||
|
/**
|
||||||
|
* 日
|
||||||
|
*/
|
||||||
|
private String days;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<Integer> day;
|
||||||
|
/**
|
||||||
|
* 时
|
||||||
|
*/
|
||||||
|
private Integer hour;
|
||||||
|
/**
|
||||||
|
* 分
|
||||||
|
*/
|
||||||
|
private Integer minute;
|
||||||
|
/**
|
||||||
|
* 部门标识
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
/**
|
||||||
|
* 机库sn
|
||||||
|
*/
|
||||||
|
private String dockSn;
|
||||||
|
/**
|
||||||
|
* 是否断点续飞
|
||||||
|
*/
|
||||||
|
private Boolean isBreakpointFly;
|
||||||
|
/**
|
||||||
|
* 断点续飞最大时间
|
||||||
|
*/
|
||||||
|
private String breakMaxTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断点续飞最小时间
|
||||||
|
*/
|
||||||
|
private String breakMinTime;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String dockName;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String routeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下次执行时间
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String nextRunTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行规则
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String cronRules;
|
||||||
}
|
}
|
||||||
|
|
@ -16,41 +16,48 @@ import java.util.Date;
|
||||||
@Data
|
@Data
|
||||||
@TableName("schedule_job_log")
|
@TableName("schedule_job_log")
|
||||||
public class ScheduleJobLogEntity implements Serializable {
|
public class ScheduleJobLogEntity implements Serializable {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* id
|
|
||||||
*/
|
|
||||||
@TableId
|
|
||||||
private Long id;
|
|
||||||
/**
|
|
||||||
* 任务id
|
|
||||||
*/
|
|
||||||
private Long jobId;
|
|
||||||
/**
|
|
||||||
* spring bean名称
|
|
||||||
*/
|
|
||||||
private String beanName;
|
|
||||||
/**
|
|
||||||
* 参数
|
|
||||||
*/
|
|
||||||
private String params;
|
|
||||||
/**
|
|
||||||
* 任务状态 0:失败 1:成功
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
/**
|
|
||||||
* 失败信息
|
|
||||||
*/
|
|
||||||
private String error;
|
|
||||||
/**
|
|
||||||
* 耗时(单位:毫秒)
|
|
||||||
*/
|
|
||||||
private Integer times;
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
private Date createDate;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 任务id
|
||||||
|
*/
|
||||||
|
private Long jobId;
|
||||||
|
/**
|
||||||
|
* spring bean名称
|
||||||
|
*/
|
||||||
|
private String beanName;
|
||||||
|
/**
|
||||||
|
* 参数
|
||||||
|
*/
|
||||||
|
private String params;
|
||||||
|
/**
|
||||||
|
* 任务状态 0:失败 1:成功
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 失败信息
|
||||||
|
*/
|
||||||
|
private String error;
|
||||||
|
/**
|
||||||
|
* 耗时(单位:毫秒)
|
||||||
|
*/
|
||||||
|
private Integer times;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createDate;
|
||||||
|
/**
|
||||||
|
* 部门
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
/**
|
||||||
|
* 任务名称
|
||||||
|
*/
|
||||||
|
private String jobName;
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
package com.multictrl.modules.job.init;
|
package com.multictrl.modules.job.init;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.multictrl.modules.job.dao.ScheduleJobDao;
|
import com.multictrl.modules.job.dao.ScheduleJobDao;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
|
import com.multictrl.modules.job.utils.CronParser;
|
||||||
import com.multictrl.modules.job.utils.ScheduleUtils;
|
import com.multictrl.modules.job.utils.ScheduleUtils;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.quartz.CronTrigger;
|
import org.quartz.CronTrigger;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,14 +22,27 @@ import java.util.List;
|
||||||
* @author Sdy
|
* @author Sdy
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class JobCommandLineRunner implements CommandLineRunner {
|
public class JobCommandLineRunner implements CommandLineRunner {
|
||||||
private final Scheduler scheduler;
|
private final Scheduler scheduler;
|
||||||
private final ScheduleJobDao scheduleJobDao;
|
private final ScheduleJobDao scheduleJobDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) {
|
public void run(String... args) {
|
||||||
List<ScheduleJobEntity> scheduleJobList = scheduleJobDao.selectList(null);
|
Date now = new Date();
|
||||||
|
List<ScheduleJobEntity> scheduleJobList = scheduleJobDao.selectList(new QueryWrapper<ScheduleJobEntity>().ne("status", -1));
|
||||||
|
Iterator<ScheduleJobEntity> iterator = scheduleJobList.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
ScheduleJobEntity item = iterator.next();
|
||||||
|
Integer cronType = item.getCronType();
|
||||||
|
if (1 == cronType) {
|
||||||
|
boolean valid = CronParser.isValid(item.getCronExpression(), now);
|
||||||
|
if (!valid) {
|
||||||
|
scheduleJobDao.update(null, new UpdateWrapper<ScheduleJobEntity>().eq("id", item.getId()).set("status", -1));
|
||||||
|
iterator.remove(); // 安全删除
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (ScheduleJobEntity scheduleJob : scheduleJobList) {
|
for (ScheduleJobEntity scheduleJob : scheduleJobList) {
|
||||||
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
|
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
|
||||||
//如果不存在,则创建
|
//如果不存在,则创建
|
||||||
|
|
|
||||||
|
|
@ -22,32 +22,32 @@ public interface ScheduleJobService extends BaseService<ScheduleJobEntity> {
|
||||||
* 保存定时任务
|
* 保存定时任务
|
||||||
*/
|
*/
|
||||||
void save(ScheduleJobDTO dto);
|
void save(ScheduleJobDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新定时任务
|
* 更新定时任务
|
||||||
*/
|
*/
|
||||||
void update(ScheduleJobDTO dto);
|
void update(ScheduleJobDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除定时任务
|
* 批量删除定时任务
|
||||||
*/
|
*/
|
||||||
void deleteBatch(Long[] ids);
|
void deleteBatch(Long[] ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新定时任务状态
|
* 批量更新定时任务状态
|
||||||
*/
|
*/
|
||||||
int updateBatch(Long[] ids, int status);
|
int updateBatch(Long[] ids, int status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即执行
|
* 立即执行
|
||||||
*/
|
*/
|
||||||
void run(Long[] ids);
|
void run(Long[] ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂停运行
|
* 暂停运行
|
||||||
*/
|
*/
|
||||||
void pause(Long[] ids);
|
void pause(Long[] ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复运行
|
* 恢复运行
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -18,29 +18,29 @@ import java.util.Map;
|
||||||
@Service
|
@Service
|
||||||
public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
|
public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageData<ScheduleJobLogDTO> page(Map<String, Object> params) {
|
public PageData<ScheduleJobLogDTO> page(Map<String, Object> params) {
|
||||||
IPage<ScheduleJobLogEntity> page = baseDao.selectPage(
|
IPage<ScheduleJobLogEntity> page = baseDao.selectPage(
|
||||||
getPage(params, Constant.CREATE_DATE, false),
|
getPage(params, Constant.CREATE_DATE, false),
|
||||||
getWrapper(params)
|
getWrapper(params)
|
||||||
);
|
);
|
||||||
return getPageData(page, ScheduleJobLogDTO.class);
|
return getPageData(page, ScheduleJobLogDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryWrapper<ScheduleJobLogEntity> getWrapper(Map<String, Object> params){
|
private QueryWrapper<ScheduleJobLogEntity> getWrapper(Map<String, Object> params) {
|
||||||
String jobId = (String)params.get("jobId");
|
String jobId = (String) params.get("jobId");
|
||||||
|
|
||||||
QueryWrapper<ScheduleJobLogEntity> wrapper = new QueryWrapper<>();
|
QueryWrapper<ScheduleJobLogEntity> wrapper = new QueryWrapper<>();
|
||||||
wrapper.eq(StrUtil.isNotBlank(jobId), "job_id", jobId);
|
wrapper.eq(StrUtil.isNotBlank(jobId), "job_id", jobId);
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduleJobLogDTO get(Long id) {
|
public ScheduleJobLogDTO get(Long id) {
|
||||||
ScheduleJobLogEntity entity = baseDao.selectById(id);
|
ScheduleJobLogEntity entity = baseDao.selectById(id);
|
||||||
|
|
||||||
return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class);
|
return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.multictrl.modules.job.service.impl;
|
package com.multictrl.modules.job.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
|
@ -11,42 +12,73 @@ import com.multictrl.modules.job.dao.ScheduleJobDao;
|
||||||
import com.multictrl.modules.job.dto.ScheduleJobDTO;
|
import com.multictrl.modules.job.dto.ScheduleJobDTO;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
import com.multictrl.modules.job.service.ScheduleJobService;
|
import com.multictrl.modules.job.service.ScheduleJobService;
|
||||||
|
import com.multictrl.modules.job.utils.CronGenerator;
|
||||||
|
import com.multictrl.modules.job.utils.CronParser;
|
||||||
|
import com.multictrl.modules.job.utils.CronToChinese;
|
||||||
import com.multictrl.modules.job.utils.ScheduleUtils;
|
import com.multictrl.modules.job.utils.ScheduleUtils;
|
||||||
import lombok.AllArgsConstructor;
|
import com.multictrl.modules.security.user.SecurityUser;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@AllArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
|
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
|
||||||
private final Scheduler scheduler;
|
private final Scheduler scheduler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageData<ScheduleJobDTO> page(Map<String, Object> params) {
|
public PageData<ScheduleJobDTO> page(Map<String, Object> params) {
|
||||||
IPage<ScheduleJobEntity> page = baseDao.selectPage(
|
IPage<ScheduleJobEntity> page = baseDao.pageList(
|
||||||
getPage(params, Constant.CREATE_DATE, false),
|
getPage(params, Constant.CREATE_DATE, false),
|
||||||
getWrapper(params)
|
getWrapper(params)
|
||||||
);
|
);
|
||||||
|
page.getRecords().forEach(item -> {
|
||||||
|
String days = item.getDays();
|
||||||
|
if (StrUtil.isNotEmpty(days)) {
|
||||||
|
List<Integer> dayList = Arrays.stream(days.trim().split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(s -> !s.isEmpty())
|
||||||
|
.map(Integer::parseInt)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
item.setDay(dayList);
|
||||||
|
}
|
||||||
|
if (item.getStatus() != -1) {
|
||||||
|
String cronExpression = item.getCronExpression();
|
||||||
|
String nextTime = CronParser.getNextTime(cronExpression);
|
||||||
|
item.setNextRunTime(nextTime);
|
||||||
|
}
|
||||||
|
item.setCronRules(CronToChinese.convert(item.getYear(), item.getMonth(), item.getDays(), item.getHour(), item.getMinute(), item.getCronType()));
|
||||||
|
});
|
||||||
return getPageData(page, ScheduleJobDTO.class);
|
return getPageData(page, ScheduleJobDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduleJobDTO get(Long id) {
|
public ScheduleJobDTO get(Long id) {
|
||||||
ScheduleJobEntity entity = baseDao.selectById(id);
|
ScheduleJobEntity entity = baseDao.getById(id);
|
||||||
|
if (entity != null) {
|
||||||
|
String days = entity.getDays();
|
||||||
|
List<Integer> dayList = Arrays.stream(days.trim().split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(s -> !s.isEmpty())
|
||||||
|
.map(Integer::parseInt)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
entity.setDay(dayList);
|
||||||
|
}
|
||||||
|
|
||||||
return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class);
|
return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryWrapper<ScheduleJobEntity> getWrapper(Map<String, Object> params) {
|
private QueryWrapper<ScheduleJobEntity> getWrapper(Map<String, Object> params) {
|
||||||
String beanName = (String) params.get("beanName");
|
String beanName = (String) params.get("beanName");
|
||||||
|
String jobName = (String) params.get("jobName");
|
||||||
|
|
||||||
QueryWrapper<ScheduleJobEntity> wrapper = new QueryWrapper<>();
|
QueryWrapper<ScheduleJobEntity> wrapper = new QueryWrapper<>();
|
||||||
wrapper.like(StrUtil.isNotBlank(beanName), "bean_name", beanName);
|
wrapper.like(StrUtil.isNotBlank(beanName), "s.bean_name", beanName);
|
||||||
|
wrapper.like(StrUtil.isNotBlank(jobName), "s.job_name", jobName);
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
@ -55,8 +87,12 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, Sche
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void save(ScheduleJobDTO dto) {
|
public void save(ScheduleJobDTO dto) {
|
||||||
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
|
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
|
||||||
|
entity.setDeptId(SecurityUser.getDeptId());
|
||||||
|
String cron = CronGenerator.getCron(dto.getCronType(), dto.getYear(), dto.getMonth(), dto.getDay(), dto.getHour(), dto.getMinute());
|
||||||
|
entity.setCronExpression(cron);
|
||||||
|
entity.setDays(StrUtil.join(",", dto.getDay()));
|
||||||
|
|
||||||
entity.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
|
entity.setStatus(Constant.ScheduleStatus.PAUSE.getValue());
|
||||||
this.insert(entity);
|
this.insert(entity);
|
||||||
|
|
||||||
ScheduleUtils.createScheduleJob(scheduler, entity);
|
ScheduleUtils.createScheduleJob(scheduler, entity);
|
||||||
|
|
@ -66,8 +102,16 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, Sche
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void update(ScheduleJobDTO dto) {
|
public void update(ScheduleJobDTO dto) {
|
||||||
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
|
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
|
||||||
|
entity.setDeptId(SecurityUser.getDeptId());
|
||||||
ScheduleUtils.updateScheduleJob(scheduler, entity);
|
String cron = CronGenerator.getCron(dto.getCronType(), dto.getYear(), dto.getMonth(), dto.getDay(), dto.getHour(), dto.getMinute());
|
||||||
|
entity.setCronExpression(cron);
|
||||||
|
entity.setDays(StrUtil.join(",", dto.getDay()));
|
||||||
|
if (dto.getStatus() == Constant.ScheduleStatus.FAILURE.getValue()) {
|
||||||
|
entity.setStatus(Constant.ScheduleStatus.PAUSE.getValue());
|
||||||
|
ScheduleUtils.createScheduleJob(scheduler, entity);
|
||||||
|
} else {
|
||||||
|
ScheduleUtils.updateScheduleJob(scheduler, entity);
|
||||||
|
}
|
||||||
|
|
||||||
this.updateById(entity);
|
this.updateById(entity);
|
||||||
}
|
}
|
||||||
|
|
@ -94,29 +138,63 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, Sche
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void run(Long[] ids) {
|
public void run(Long[] ids) {
|
||||||
|
List<Long> failure = new ArrayList<>();
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
ScheduleUtils.run(scheduler, this.selectById(id));
|
//是否判断过期
|
||||||
|
ScheduleJobDTO jobDTO = get(id);
|
||||||
|
int result = ScheduleUtils.run(scheduler, this.selectById(id), jobDTO.getCronType() == 1);
|
||||||
|
if (result == Constant.ScheduleStatus.FAILURE.getValue()) {
|
||||||
|
failure.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(failure)) {
|
||||||
|
updateBatch(failure.toArray(new Long[0]), Constant.ScheduleStatus.FAILURE.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void pause(Long[] ids) {
|
public void pause(Long[] ids) {
|
||||||
|
List<Long> failure = new ArrayList<>();
|
||||||
|
List<Long> normal = new ArrayList<>();
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
ScheduleUtils.pauseJob(scheduler, id);
|
//是否判断过期
|
||||||
|
ScheduleJobDTO jobDTO = get(id);
|
||||||
|
int result = ScheduleUtils.pauseJob(scheduler, id, jobDTO.getCronType() == 1);
|
||||||
|
if (result == Constant.ScheduleStatus.FAILURE.getValue()) {
|
||||||
|
failure.add(id);
|
||||||
|
} else {
|
||||||
|
normal.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(failure)) {
|
||||||
|
updateBatch(failure.toArray(new Long[0]), Constant.ScheduleStatus.FAILURE.getValue());
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(normal)) {
|
||||||
|
updateBatch(normal.toArray(new Long[0]), Constant.ScheduleStatus.PAUSE.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBatch(ids, Constant.ScheduleStatus.PAUSE.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void resume(Long[] ids) {
|
public void resume(Long[] ids) {
|
||||||
|
List<Long> failure = new ArrayList<>();
|
||||||
|
List<Long> normal = new ArrayList<>();
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
ScheduleUtils.resumeJob(scheduler, id);
|
//是否判断过期
|
||||||
|
ScheduleJobDTO jobDTO = get(id);
|
||||||
|
int result = ScheduleUtils.resumeJob(scheduler, id, jobDTO.getCronType() == 1);
|
||||||
|
if (result == Constant.ScheduleStatus.FAILURE.getValue()) {
|
||||||
|
failure.add(id);
|
||||||
|
} else {
|
||||||
|
normal.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(failure)) {
|
||||||
|
updateBatch(failure.toArray(new Long[0]), Constant.ScheduleStatus.FAILURE.getValue());
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(normal)) {
|
||||||
|
updateBatch(normal.toArray(new Long[0]), Constant.ScheduleStatus.NORMAL.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBatch(ids, Constant.ScheduleStatus.NORMAL.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.multictrl.modules.job.task;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.multictrl.common.constant.BusinessConstant;
|
||||||
|
import com.multictrl.common.utils.CacheUtils;
|
||||||
|
import com.multictrl.common.utils.JsonUtils;
|
||||||
|
import com.multictrl.common.utils.Utils;
|
||||||
|
import com.multictrl.modules.business.dto.flight.FlightExecute;
|
||||||
|
import com.multictrl.modules.business.service.FlightTaskService;
|
||||||
|
import com.multictrl.modules.business.service.RouteFlightService;
|
||||||
|
import com.multictrl.modules.job.dto.ScheduleJobDTO;
|
||||||
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
|
import com.multictrl.modules.job.service.ScheduleJobService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 航线任务
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026/5/28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component("routeTask")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RouteTask implements ITask {
|
||||||
|
private final ScheduleJobService scheduleJobService;
|
||||||
|
private final RouteFlightService routeFlightService;
|
||||||
|
private final FlightTaskService flightTaskService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String params) {
|
||||||
|
JSONObject jsonObject = JsonUtils.parseObject(params, JSONObject.class);
|
||||||
|
if (jsonObject == null) {
|
||||||
|
log.error("计划飞行任务无效,拒绝执行:{}", params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Long jobId = jsonObject.getLong("jobId");
|
||||||
|
Integer cronType = jsonObject.getInt("cronType");
|
||||||
|
if (cronType == 1) {
|
||||||
|
//一次性任务 执行完失效 不然初始化job会因为时间过期而报错
|
||||||
|
ScheduleJobEntity scheduleJobEntity = new ScheduleJobEntity();
|
||||||
|
scheduleJobEntity.setStatus(-1);
|
||||||
|
scheduleJobEntity.setId(jobId);
|
||||||
|
scheduleJobService.updateById(scheduleJobEntity);
|
||||||
|
}
|
||||||
|
ScheduleJobDTO dto = scheduleJobService.get(jobId);
|
||||||
|
String dockSn = dto.getDockSn();
|
||||||
|
//执行任务
|
||||||
|
FlightExecute flightExecute = new FlightExecute();
|
||||||
|
flightExecute.setRouteId(Long.parseLong(dto.getParams()));
|
||||||
|
routeFlightService.flightExecute(dockSn, flightExecute, false);
|
||||||
|
//添加日志
|
||||||
|
Utils.sleep(1000);
|
||||||
|
String taskId = (String) CacheUtils.get(BusinessConstant.WORKING_TASK_ID + dockSn);
|
||||||
|
flightTaskService.addJobRouteTask(taskId, jobId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.multictrl.modules.job.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import org.quartz.CronExpression;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cron表达式生成器
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 2025/6/27
|
||||||
|
*/
|
||||||
|
public class CronGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. 某一天的几点执行(年、月、日、小时、分钟)
|
||||||
|
*
|
||||||
|
* @param year 年(如 2024)
|
||||||
|
* @param month 月(1-12)
|
||||||
|
* @param day 日期(1-31)
|
||||||
|
* @param hour 小时(0-23)
|
||||||
|
* @param minute 分钟(0-59)
|
||||||
|
* @return Cron 表达式
|
||||||
|
*/
|
||||||
|
public static String generateOnceCron(int year, int month, List<Integer> day, int hour, int minute) {
|
||||||
|
return String.format("0 %d %d %d %d ? %d", minute, hour, day.get(0), month, year);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2. 每天的几点执行(小时、分钟)
|
||||||
|
*
|
||||||
|
* @param hour 小时(0-23)
|
||||||
|
* @param minute 分钟(0-59)
|
||||||
|
* @return Cron 表达式
|
||||||
|
*/
|
||||||
|
public static String generateDailyCron(int hour, int minute) {
|
||||||
|
return String.format("0 %d %d * * ? *", minute, hour);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3. 每周的周几几点执行(周几、小时、分钟)
|
||||||
|
*
|
||||||
|
* @param dayOfWeek 周几(1-7,1=周一)
|
||||||
|
* @param hour 小时(0-23)
|
||||||
|
* @param minute 分钟(0-59)
|
||||||
|
* @return Cron 表达式
|
||||||
|
*/
|
||||||
|
public static String generateWeeklyCron(List<Integer> dayOfWeek, int hour, int minute) {
|
||||||
|
// 转换星期表示(将国内习惯的1-7转换为Cron表达式的1-7)
|
||||||
|
// 国内习惯:1=周一, 2=周二, 3=周三, 4=周四, 5=周五, 6=周六, 7=周日
|
||||||
|
// Cron表达式:1=周日, 2=周一, 3=周二, 4=周三, 5=周四, 6=周五, 7=周六
|
||||||
|
List<Integer> cronDays = dayOfWeek.stream()
|
||||||
|
.map(d -> {
|
||||||
|
if (d == 7) return 1; // 7(周日) → 1(周日)
|
||||||
|
return d + 1; // 1(周一)→2, 2(周二)→3, ... 6(周六)→7
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return String.format("0 %d %d ? * %s *", minute, hour, StrUtil.join(",", cronDays));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4. 每月的几号几点执行(日期、小时、分钟)
|
||||||
|
*
|
||||||
|
* @param dayOfMonth 日期(1-31)
|
||||||
|
* @param hour 小时(0-23)
|
||||||
|
* @param minute 分钟(0-59)
|
||||||
|
* @return Cron 表达式
|
||||||
|
*/
|
||||||
|
public static String generateMonthlyCron(List<Integer> dayOfMonth, int hour, int minute) {
|
||||||
|
return String.format("0 %d %d %s * ? *", minute, hour, StrUtil.join(",", dayOfMonth));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选:验证 Cron 表达式是否合法(需引入 quartz 或 cronutils 依赖)
|
||||||
|
public static boolean isValid(String cronExpression) {
|
||||||
|
try {
|
||||||
|
new CronExpression(cronExpression); // 需要 quartz 依赖
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取cron表达式
|
||||||
|
public static String getCron(Integer cronType, Integer year, Integer month, List<Integer> day, Integer hour, Integer minute) {
|
||||||
|
return switch (cronType) {
|
||||||
|
case 1 -> generateOnceCron(year, month, day, hour, minute);
|
||||||
|
case 2 -> generateDailyCron(hour, minute);
|
||||||
|
case 3 -> generateWeeklyCron(day, hour, minute);
|
||||||
|
case 4 -> generateMonthlyCron(day, hour, minute);
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.multictrl.modules.job.utils;
|
||||||
|
|
||||||
|
import com.multictrl.common.exception.ExceptionUtils;
|
||||||
|
import com.multictrl.common.utils.DateUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.CronExpression;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cron表达式解析
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2025/7/22
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CronParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下一次执行时间
|
||||||
|
*/
|
||||||
|
public static String getNextTime(String cronExpression) {
|
||||||
|
try {
|
||||||
|
CronExpression cron = new CronExpression(cronExpression);
|
||||||
|
Date now = new Date(); // 当前时间
|
||||||
|
Date nextTime = cron.getNextValidTimeAfter(now); // 获取下一次执行时间
|
||||||
|
return DateUtils.format(nextTime, "yyyy-MM-dd HH:mm");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.error(ExceptionUtils.getErrorStackTrace(e));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否有效
|
||||||
|
*/
|
||||||
|
public static boolean isValid(String cronExpression, Date now) {
|
||||||
|
try {
|
||||||
|
boolean validExpression = CronExpression.isValidExpression(cronExpression);
|
||||||
|
if (validExpression) {
|
||||||
|
CronExpression cron = new CronExpression(cronExpression);
|
||||||
|
Date nextFireTime = cron.getNextValidTimeAfter(now);
|
||||||
|
return !(nextFireTime == null || nextFireTime.before(now));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.multictrl.modules.job.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文转换工具
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2025/7/24
|
||||||
|
*/
|
||||||
|
public class CronToChinese {
|
||||||
|
/**
|
||||||
|
* 将 Cron 表达式转换为中文描述
|
||||||
|
*/
|
||||||
|
public static String convert(Integer year, Integer month, String days, Integer hour, Integer minute, Integer cronType) {
|
||||||
|
switch (cronType) {
|
||||||
|
case 1:
|
||||||
|
return year + "年" + month + "月" + days + "日" + hour + "点" + minute + "分执行";
|
||||||
|
case 2:
|
||||||
|
return "每天" + hour + "点" + minute + "分执行";
|
||||||
|
case 3:
|
||||||
|
String weekday = "";
|
||||||
|
String[] split = days.split(",");
|
||||||
|
for (String s : split) {
|
||||||
|
if (s.equals("1")) {
|
||||||
|
weekday += "周一、";
|
||||||
|
} else if (s.equals("2")) {
|
||||||
|
weekday += "周二、";
|
||||||
|
} else if (s.equals("3")) {
|
||||||
|
weekday += "周三、";
|
||||||
|
} else if (s.equals("4")) {
|
||||||
|
weekday += "周四、";
|
||||||
|
} else if (s.equals("5")) {
|
||||||
|
weekday += "周五、";
|
||||||
|
} else if (s.equals("6")) {
|
||||||
|
weekday += "周六、";
|
||||||
|
} else if (s.equals("7")) {
|
||||||
|
weekday += "周日、";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "每周" + weekday.substring(0, weekday.length() - 1) + "的" + hour + "点" + minute + "分执行";
|
||||||
|
case 4:
|
||||||
|
String monthday = "";
|
||||||
|
String[] day = days.split(",");
|
||||||
|
for (String s : day) {
|
||||||
|
monthday += s + "号、";
|
||||||
|
}
|
||||||
|
return "每月" + monthday.substring(0, monthday.length() - 1) + "的" + hour + "点" + minute + "分执行";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例用法
|
||||||
|
/*public static void main(String[] args) {
|
||||||
|
System.out.println(convert(2025, 7, "24", 3, 23, 1));
|
||||||
|
// 输出:2025年7月每月24日的上午3点23分执行
|
||||||
|
|
||||||
|
System.out.println(convert(0, 0, "", 12, 29, 2));
|
||||||
|
// 输出:每天中午12点29分执行
|
||||||
|
|
||||||
|
System.out.println(convert(0, 0, "1,3,7", 11, 55, 3));
|
||||||
|
// 输出:每周一、周三、周日上午11点55分执行
|
||||||
|
|
||||||
|
System.out.println(convert(0, 0, "1,3,5", 12, 56, 4));
|
||||||
|
// 输出:每月1日、3日和5日的中午12点56分执行
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package com.multictrl.modules.job.utils;
|
package com.multictrl.modules.job.utils;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import com.multictrl.common.constant.Constant;
|
import com.multictrl.common.constant.Constant;
|
||||||
import com.multictrl.common.exception.ExceptionUtils;
|
import com.multictrl.common.exception.ExceptionUtils;
|
||||||
|
import com.multictrl.common.utils.JsonUtils;
|
||||||
import com.multictrl.common.utils.SpringContextUtils;
|
import com.multictrl.common.utils.SpringContextUtils;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobLogEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobLogEntity;
|
||||||
import com.multictrl.modules.job.service.ScheduleJobLogService;
|
import com.multictrl.modules.job.service.ScheduleJobLogService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -15,58 +16,60 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务
|
* 定时任务
|
||||||
*
|
|
||||||
* @author Sdy
|
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
public class ScheduleJob extends QuartzJobBean {
|
public class ScheduleJob extends QuartzJobBean {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void executeInternal(JobExecutionContext context) {
|
protected void executeInternal(JobExecutionContext context) {
|
||||||
ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap().
|
ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap().
|
||||||
get(ScheduleUtils.JOB_PARAM_KEY);
|
get(ScheduleUtils.JOB_PARAM_KEY);
|
||||||
|
|
||||||
//数据库保存执行记录
|
//数据库保存执行记录
|
||||||
ScheduleJobLogEntity logEntity = new ScheduleJobLogEntity();
|
ScheduleJobLogEntity log = new ScheduleJobLogEntity();
|
||||||
logEntity.setJobId(scheduleJob.getId());
|
log.setJobId(scheduleJob.getId());
|
||||||
logEntity.setBeanName(scheduleJob.getBeanName());
|
log.setBeanName(scheduleJob.getBeanName());
|
||||||
logEntity.setParams(scheduleJob.getParams());
|
log.setParams(scheduleJob.getParams());
|
||||||
logEntity.setCreateDate(new Date());
|
log.setCreateDate(new Date());
|
||||||
|
log.setDeptId(scheduleJob.getDeptId());
|
||||||
|
log.setJobName(scheduleJob.getJobName());
|
||||||
|
|
||||||
//任务开始时间
|
//任务开始时间
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//执行任务
|
//执行任务
|
||||||
log.info("任务准备执行,任务ID:{}", scheduleJob.getId());
|
logger.info("任务准备执行,任务ID:{}", scheduleJob.getId());
|
||||||
Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
|
Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
|
||||||
Method method = target.getClass().getDeclaredMethod("run", String.class);
|
Method method = target.getClass().getDeclaredMethod("run", String.class);
|
||||||
method.invoke(target, scheduleJob.getParams());
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.set("jobId", scheduleJob.getId());
|
||||||
|
jsonObject.set("cronType", scheduleJob.getCronType());
|
||||||
|
method.invoke(target, JsonUtils.toJsonString(jsonObject));
|
||||||
|
|
||||||
//任务执行总时长
|
//任务执行总时长
|
||||||
long times = System.currentTimeMillis() - startTime;
|
long times = System.currentTimeMillis() - startTime;
|
||||||
logEntity.setTimes((int)times);
|
log.setTimes((int) times);
|
||||||
//任务状态
|
//任务状态
|
||||||
logEntity.setStatus(Constant.SUCCESS);
|
log.setStatus(Constant.SUCCESS);
|
||||||
|
|
||||||
log.info("任务执行完毕,任务ID:{} 总共耗时:{} 毫秒", scheduleJob.getId(), times);
|
logger.info("任务执行完毕,任务ID:{} 总共耗时:{} 毫秒", scheduleJob.getId(), times);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e);
|
logger.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e);
|
||||||
|
|
||||||
//任务执行总时长
|
//任务执行总时长
|
||||||
long times = System.currentTimeMillis() - startTime;
|
long times = System.currentTimeMillis() - startTime;
|
||||||
logEntity.setTimes((int)times);
|
log.setTimes((int) times);
|
||||||
|
|
||||||
//任务状态
|
//任务状态
|
||||||
logEntity.setStatus(Constant.FAIL);
|
log.setStatus(Constant.FAIL);
|
||||||
logEntity.setError(ExceptionUtils.getErrorStackTrace(e));
|
log.setError(ExceptionUtils.getErrorStackTrace(e));
|
||||||
}finally {
|
} finally {
|
||||||
//获取spring bean
|
//获取spring bean
|
||||||
ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class);
|
ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class);
|
||||||
scheduleJobLogService.insert(logEntity);
|
scheduleJobLogService.insert(log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,29 +2,32 @@ package com.multictrl.modules.job.utils;
|
||||||
|
|
||||||
import com.multictrl.common.constant.Constant;
|
import com.multictrl.common.constant.Constant;
|
||||||
import com.multictrl.common.exception.ErrorCode;
|
import com.multictrl.common.exception.ErrorCode;
|
||||||
|
import com.multictrl.common.exception.ExceptionUtils;
|
||||||
import com.multictrl.common.exception.RenException;
|
import com.multictrl.common.exception.RenException;
|
||||||
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
import com.multictrl.modules.job.entity.ScheduleJobEntity;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.quartz.*;
|
import org.quartz.*;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务工具类
|
* 定时任务工具类
|
||||||
*
|
|
||||||
* @author Sdy
|
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class ScheduleUtils {
|
public class ScheduleUtils {
|
||||||
private final static String JOB_NAME = "TASK_";
|
private final static String JOB_NAME = "TASK_";
|
||||||
/**
|
/**
|
||||||
* 任务调度参数key
|
* 任务调度参数key
|
||||||
*/
|
*/
|
||||||
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
|
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取触发器key
|
* 获取触发器key
|
||||||
*/
|
*/
|
||||||
public static TriggerKey getTriggerKey(Long jobId) {
|
public static TriggerKey getTriggerKey(Long jobId) {
|
||||||
return TriggerKey.triggerKey(JOB_NAME + jobId);
|
return TriggerKey.triggerKey(JOB_NAME + jobId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取jobKey
|
* 获取jobKey
|
||||||
*/
|
*/
|
||||||
|
|
@ -48,12 +51,12 @@ public class ScheduleUtils {
|
||||||
*/
|
*/
|
||||||
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||||
try {
|
try {
|
||||||
//构建job信息
|
//构建job信息
|
||||||
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build();
|
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build();
|
||||||
|
|
||||||
//表达式调度构建器
|
//表达式调度构建器
|
||||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
||||||
.withMisfireHandlingInstructionDoNothing();
|
.withMisfireHandlingInstructionDoNothing();
|
||||||
|
|
||||||
//按新的cronExpression表达式构建一个新的trigger
|
//按新的cronExpression表达式构建一个新的trigger
|
||||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
|
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
|
||||||
|
|
@ -62,16 +65,16 @@ public class ScheduleUtils {
|
||||||
jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
|
jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
|
||||||
|
|
||||||
scheduler.scheduleJob(jobDetail, trigger);
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
|
||||||
//暂停任务
|
//暂停任务
|
||||||
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
|
if (scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()) {
|
||||||
pauseJob(scheduler, scheduleJob.getId());
|
pauseJob(scheduler, scheduleJob.getId(), false);
|
||||||
}
|
}
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新定时任务
|
* 更新定时任务
|
||||||
*/
|
*/
|
||||||
|
|
@ -81,23 +84,23 @@ public class ScheduleUtils {
|
||||||
|
|
||||||
//表达式调度构建器
|
//表达式调度构建器
|
||||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
||||||
.withMisfireHandlingInstructionDoNothing();
|
.withMisfireHandlingInstructionDoNothing();
|
||||||
|
|
||||||
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
|
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
|
||||||
|
|
||||||
//按新的cronExpression表达式重新构建trigger
|
//按新的cronExpression表达式重新构建trigger
|
||||||
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
||||||
|
|
||||||
//参数
|
//参数
|
||||||
trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
|
trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
|
||||||
|
|
||||||
scheduler.rescheduleJob(triggerKey, trigger);
|
scheduler.rescheduleJob(triggerKey, trigger);
|
||||||
|
|
||||||
//暂停任务
|
//暂停任务
|
||||||
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
|
if (scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()) {
|
||||||
pauseJob(scheduler, scheduleJob.getId());
|
pauseJob(scheduler, scheduleJob.getId(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
|
|
@ -106,13 +109,20 @@ public class ScheduleUtils {
|
||||||
/**
|
/**
|
||||||
* 立即执行任务
|
* 立即执行任务
|
||||||
*/
|
*/
|
||||||
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
public static int run(Scheduler scheduler, ScheduleJobEntity scheduleJob, boolean validateExpired) {
|
||||||
try {
|
try {
|
||||||
//参数
|
Long jobId = scheduleJob.getId();
|
||||||
JobDataMap dataMap = new JobDataMap();
|
if (validateExpired && isJobExpired(scheduler, jobId)) {
|
||||||
dataMap.put(JOB_PARAM_KEY, scheduleJob);
|
removeExpiredJob(scheduler, jobId);
|
||||||
|
return Constant.ScheduleStatus.FAILURE.getValue();
|
||||||
scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
|
}
|
||||||
|
|
||||||
|
//参数
|
||||||
|
JobDataMap dataMap = new JobDataMap();
|
||||||
|
dataMap.put(JOB_PARAM_KEY, scheduleJob);
|
||||||
|
|
||||||
|
scheduler.triggerJob(getJobKey(jobId), dataMap);
|
||||||
|
return Constant.ScheduleStatus.NORMAL.getValue();
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
|
|
@ -121,9 +131,15 @@ public class ScheduleUtils {
|
||||||
/**
|
/**
|
||||||
* 暂停任务
|
* 暂停任务
|
||||||
*/
|
*/
|
||||||
public static void pauseJob(Scheduler scheduler, Long jobId) {
|
public static int pauseJob(Scheduler scheduler, Long jobId, boolean validateExpired) {
|
||||||
try {
|
try {
|
||||||
|
if (validateExpired && isJobExpired(scheduler, jobId)) {
|
||||||
|
removeExpiredJob(scheduler, jobId);
|
||||||
|
return Constant.ScheduleStatus.FAILURE.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
scheduler.pauseJob(getJobKey(jobId));
|
scheduler.pauseJob(getJobKey(jobId));
|
||||||
|
return Constant.ScheduleStatus.PAUSE.getValue();
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
|
|
@ -132,9 +148,15 @@ public class ScheduleUtils {
|
||||||
/**
|
/**
|
||||||
* 恢复任务
|
* 恢复任务
|
||||||
*/
|
*/
|
||||||
public static void resumeJob(Scheduler scheduler, Long jobId) {
|
public static int resumeJob(Scheduler scheduler, Long jobId, boolean validateExpired) {
|
||||||
try {
|
try {
|
||||||
|
if (validateExpired && isJobExpired(scheduler, jobId)) {
|
||||||
|
removeExpiredJob(scheduler, jobId);
|
||||||
|
return Constant.ScheduleStatus.FAILURE.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
scheduler.resumeJob(getJobKey(jobId));
|
scheduler.resumeJob(getJobKey(jobId));
|
||||||
|
return Constant.ScheduleStatus.NORMAL.getValue();
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
|
|
@ -150,4 +172,41 @@ public class ScheduleUtils {
|
||||||
throw new RenException(ErrorCode.JOB_ERROR, e);
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查任务是否已过期
|
||||||
|
*/
|
||||||
|
private static boolean isJobExpired(Scheduler scheduler, Long jobId) {
|
||||||
|
try {
|
||||||
|
Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(JOB_NAME + jobId));
|
||||||
|
Date nextFireTime = trigger.getNextFireTime();
|
||||||
|
return nextFireTime != null && nextFireTime.before(new Date());
|
||||||
|
/* TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + jobId);
|
||||||
|
// 1. Trigger 不存在(已被删除)→ 视为过期
|
||||||
|
if (!scheduler.checkExists(triggerKey)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 2. 检查 Trigger 状态:仅 COMPLETE 表示“已永久完成”
|
||||||
|
Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
|
||||||
|
return state == Trigger.TriggerState.COMPLETE;*/
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.debug("判断任务 {} 是否过期失败", jobId);
|
||||||
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除过期任务(从调度器中移除并更新状态)
|
||||||
|
*/
|
||||||
|
private static void removeExpiredJob(Scheduler scheduler, Long jobId) {
|
||||||
|
try {
|
||||||
|
// 从调度器中移除
|
||||||
|
scheduler.deleteJob(getJobKey(jobId));
|
||||||
|
|
||||||
|
log.debug("任务 {} 已过期,已从调度器中移除并标记为失效", jobId);
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.error("移除过期任务失败: {}", ExceptionUtils.getErrorStackTrace(e));
|
||||||
|
throw new RenException(ErrorCode.JOB_ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,13 +2,29 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="com.multictrl.modules.job.dao.ScheduleJobDao">
|
<mapper namespace="com.multictrl.modules.job.dao.ScheduleJobDao">
|
||||||
|
|
||||||
<!-- 批量更新状态 -->
|
<!-- 批量更新状态 -->
|
||||||
<update id="updateBatch">
|
<update id="updateBatch">
|
||||||
update schedule_job set status = #{status} where id in
|
update schedule_job set status = #{status} where id in
|
||||||
<foreach item="id" collection="ids" open="(" separator="," close=")">
|
<foreach item="id" collection="ids" open="(" separator="," close=")">
|
||||||
#{id}
|
#{id}
|
||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<select id="pageList" resultType="com.multictrl.modules.job.entity.ScheduleJobEntity">
|
||||||
|
SELECT s.*, uh.dock_name, ur.route_name
|
||||||
|
FROM schedule_job s
|
||||||
|
left join bus_dock uh on s.dock_sn = uh.dock_sn
|
||||||
|
left join bus_route ur on CAST(s.params AS int8) = ur.id
|
||||||
|
${ew.customSqlSegment}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getById" resultType="com.multictrl.modules.job.entity.ScheduleJobEntity">
|
||||||
|
SELECT s.*, uh.dock_name, ur.route_name
|
||||||
|
FROM schedule_job s
|
||||||
|
left join bus_dock uh on s.dock_sn = uh.dock_sn
|
||||||
|
left join bus_route ur on CAST(s.params AS int8) = ur.id
|
||||||
|
where s.id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -3,5 +3,4 @@
|
||||||
|
|
||||||
<mapper namespace="com.multictrl.modules.job.dao.ScheduleJobLogDao">
|
<mapper namespace="com.multictrl.modules.job.dao.ScheduleJobLogDao">
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -25,7 +25,7 @@ public interface Constant {
|
||||||
*/
|
*/
|
||||||
Long DEPT_ROOT = 0L;
|
Long DEPT_ROOT = 0L;
|
||||||
/**
|
/**
|
||||||
* 升序
|
* 升序
|
||||||
*/
|
*/
|
||||||
String ASC = "asc";
|
String ASC = "asc";
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,7 +74,11 @@ public interface Constant {
|
||||||
/**
|
/**
|
||||||
* 正常
|
* 正常
|
||||||
*/
|
*/
|
||||||
NORMAL(1);
|
NORMAL(1),
|
||||||
|
/**
|
||||||
|
* 失效
|
||||||
|
*/
|
||||||
|
FAILURE(-1);
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -632,20 +632,32 @@ ON TABLE "public"."bus_waypoint_action" IS '航点动作信息';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for schedule_job
|
-- Table structure for schedule_job
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS "public"."schedule_job";
|
DROP TABLE IF EXISTS "public"."schedule_job";
|
||||||
CREATE TABLE "public"."schedule_job"
|
CREATE TABLE "public"."schedule_job"
|
||||||
(
|
(
|
||||||
"id" int8 NOT NULL,
|
"id" int8 NOT NULL,
|
||||||
"bean_name" varchar(200) COLLATE "pg_catalog"."default",
|
"bean_name" varchar(200) COLLATE "pg_catalog"."default",
|
||||||
"params" varchar(2000) COLLATE "pg_catalog"."default",
|
"params" varchar(2000) COLLATE "pg_catalog"."default",
|
||||||
"cron_expression" varchar(100) COLLATE "pg_catalog"."default",
|
"cron_expression" varchar(100) COLLATE "pg_catalog"."default",
|
||||||
"status" int4,
|
"status" int4,
|
||||||
"remark" varchar(255) COLLATE "pg_catalog"."default",
|
"remark" varchar(255) COLLATE "pg_catalog"."default",
|
||||||
"creator" int8,
|
"creator" int8,
|
||||||
"create_date" timestamp(6),
|
"create_date" timestamp(6),
|
||||||
"updater" int8,
|
"updater" int8,
|
||||||
"update_date" timestamp(6)
|
"update_date" timestamp(6),
|
||||||
|
"job_name" varchar(50) COLLATE "pg_catalog"."default",
|
||||||
|
"cron_type" int4,
|
||||||
|
"year" int4,
|
||||||
|
"month" int4,
|
||||||
|
"days" varchar(100) COLLATE "pg_catalog"."default",
|
||||||
|
"hour" int4,
|
||||||
|
"minute" int4,
|
||||||
|
"dept_id" int8,
|
||||||
|
"params_remark" varchar(200) COLLATE "pg_catalog"."default",
|
||||||
|
"dock_sn" varchar(50) COLLATE "pg_catalog"."default",
|
||||||
|
"is_breakpoint_fly" bool,
|
||||||
|
"break_max_time" varchar(50) COLLATE "pg_catalog"."default",
|
||||||
|
"break_min_time" varchar(50) COLLATE "pg_catalog"."default"
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
COMMENT
|
COMMENT
|
||||||
|
|
@ -657,7 +669,7 @@ ON COLUMN "public"."schedule_job"."params" IS '参数';
|
||||||
COMMENT
|
COMMENT
|
||||||
ON COLUMN "public"."schedule_job"."cron_expression" IS 'cron表达式';
|
ON COLUMN "public"."schedule_job"."cron_expression" IS 'cron表达式';
|
||||||
COMMENT
|
COMMENT
|
||||||
ON COLUMN "public"."schedule_job"."status" IS '任务状态 0:暂停 1:正常';
|
ON COLUMN "public"."schedule_job"."status" IS '任务状态 0:暂停 1:正常 -1:失效';
|
||||||
COMMENT
|
COMMENT
|
||||||
ON COLUMN "public"."schedule_job"."remark" IS '备注';
|
ON COLUMN "public"."schedule_job"."remark" IS '备注';
|
||||||
COMMENT
|
COMMENT
|
||||||
|
|
@ -669,12 +681,33 @@ ON COLUMN "public"."schedule_job"."updater" IS '更新者';
|
||||||
COMMENT
|
COMMENT
|
||||||
ON COLUMN "public"."schedule_job"."update_date" IS '更新时间';
|
ON COLUMN "public"."schedule_job"."update_date" IS '更新时间';
|
||||||
COMMENT
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."job_name" IS '任务名称';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."cron_type" IS '定时类型 1指定时间 2每天几点 3每周周几几点 4每月几号几点';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."year" IS '年';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."month" IS '月';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."days" IS '日';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."hour" IS '时';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."minute" IS '分';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."dept_id" IS '部门标识';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."params_remark" IS '参数备注';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."dock_sn" IS '机库sn';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."is_breakpoint_fly" IS '是否断点续飞';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."break_max_time" IS '断点续飞最大时间';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job"."break_min_time" IS '断点续飞最小时间';
|
||||||
|
COMMENT
|
||||||
ON TABLE "public"."schedule_job" IS '定时任务';
|
ON TABLE "public"."schedule_job" IS '定时任务';
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Records of schedule_job
|
|
||||||
-- ----------------------------
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for schedule_job_log
|
-- Table structure for schedule_job_log
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
|
@ -688,7 +721,9 @@ CREATE TABLE "public"."schedule_job_log"
|
||||||
"status" int4,
|
"status" int4,
|
||||||
"error" varchar(2000) COLLATE "pg_catalog"."default",
|
"error" varchar(2000) COLLATE "pg_catalog"."default",
|
||||||
"times" int4,
|
"times" int4,
|
||||||
"create_date" timestamp(6)
|
"create_date" timestamp(6),
|
||||||
|
"dept_id" int8,
|
||||||
|
"job_name" varchar(50) COLLATE "pg_catalog"."default"
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
COMMENT
|
COMMENT
|
||||||
|
|
@ -704,6 +739,10 @@ ON COLUMN "public"."schedule_job_log"."error" IS '失败信息';
|
||||||
COMMENT
|
COMMENT
|
||||||
ON COLUMN "public"."schedule_job_log"."times" IS '耗时(单位:毫秒)';
|
ON COLUMN "public"."schedule_job_log"."times" IS '耗时(单位:毫秒)';
|
||||||
COMMENT
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job_log"."dept_id" IS '部门标识';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."schedule_job_log"."job_name" IS '任务名称';
|
||||||
|
COMMENT
|
||||||
ON TABLE "public"."schedule_job_log" IS '定时任务日志';
|
ON TABLE "public"."schedule_job_log" IS '定时任务日志';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue