[代码完善](v2.5): v2.5 beta 定时任务子任务优化完成

1、定时任务中子任务按顺序执行
2、如果子任务执行途中报错,则不会再执行后面的子任务
3、子任务按逗号隔开,中英文逗号都可以
4、子任务中不能添加自身的ID,不然会无限循环

2.5 进度: https://www.ydyno.com/archives/1225.html
pull/372/head
ZhengJie 2020-05-24 14:57:59 +08:00
parent 21f8b4ebb5
commit 0f9a9b1c83
5 changed files with 59 additions and 17 deletions

View File

@ -42,6 +42,10 @@ public class QuartzJob extends BaseEntity implements Serializable {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Transient
@ApiModelProperty(value = "用于子任务唯一标识", hidden = true)
private String uuid;
@ApiModelProperty(value = "定时器名称")
private String jobName;

View File

@ -19,7 +19,6 @@ import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.domain.QuartzLog;
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@ -113,4 +112,11 @@ public interface QuartzJobService {
* @throws IOException /
*/
void downloadLog(List<QuartzLog> queryAllLog, HttpServletResponse response) throws IOException;
/**
*
* @param tasks /
* @throws InterruptedException /
*/
void executionSubJob(String[] tasks) throws InterruptedException;
}

View File

@ -15,6 +15,7 @@
*/
package me.zhengjie.modules.quartz.service.impl;
import cn.hutool.core.util.IdUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.quartz.domain.QuartzJob;
@ -24,12 +25,10 @@ import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
import me.zhengjie.modules.quartz.service.QuartzJobService;
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
import me.zhengjie.modules.quartz.utils.QuartzManage;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.*;
import org.quartz.CronExpression;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
@ -47,6 +46,7 @@ public class QuartzJobServiceImpl implements QuartzJobService {
private final QuartzJobRepository quartzJobRepository;
private final QuartzLogRepository quartzLogRepository;
private final QuartzManage quartzManage;
private final RedisUtils redisUtils;
@Override
public Object queryAll(JobQueryCriteria criteria, Pageable pageable){
@ -91,6 +91,12 @@ public class QuartzJobServiceImpl implements QuartzJobService {
if (!CronExpression.isValidExpression(resources.getCronExpression())){
throw new BadRequestException("cron表达式格式错误");
}
if(StringUtils.isNotBlank(resources.getSubTask())){
List<String> tasks = Arrays.asList(resources.getSubTask().split("[,]"));
if (tasks.contains(resources.getId().toString())) {
throw new BadRequestException("子任务中不能添加当前任务ID");
}
}
resources = quartzJobRepository.save(resources);
quartzManage.updateJobCron(resources);
}
@ -122,6 +128,31 @@ public class QuartzJobServiceImpl implements QuartzJobService {
}
}
@Async
@Override
@Transactional(rollbackFor = Exception.class)
public void executionSubJob(String[] tasks) throws InterruptedException {
for (String id : tasks) {
QuartzJob quartzJob = findById(Long.parseLong(id));
// 执行任务
String uuid = IdUtil.simpleUUID();
quartzJob.setUuid(uuid);
// 执行任务
execution(quartzJob);
// 获取执行状态,如果执行失败则停止后面的子任务执行
Boolean result = (Boolean) redisUtils.get(uuid);
while (result == null) {
// 休眠5秒再次获取子任务执行情况
Thread.sleep(5000);
result = (Boolean) redisUtils.get(uuid);
}
if(!result){
redisUtils.del(uuid);
break;
}
}
}
@Override
public void download(List<QuartzJob> quartzJobs, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();

View File

@ -26,14 +26,12 @@ import me.zhengjie.modules.quartz.domain.QuartzLog;
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
import me.zhengjie.modules.quartz.service.QuartzJobService;
import me.zhengjie.service.EmailService;
import me.zhengjie.utils.RedisUtils;
import me.zhengjie.utils.SpringContextHolder;
import me.zhengjie.utils.ThrowableUtil;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.*;
import java.util.concurrent.*;
@ -46,8 +44,6 @@ import java.util.concurrent.*;
@SuppressWarnings({"unchecked","all"})
public class ExecutionJob extends QuartzJobBean {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/** 该处仅供参考 */
private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
@ -57,6 +53,7 @@ public class ExecutionJob extends QuartzJobBean {
// 获取spring bean
QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class);
QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class);
RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
QuartzLog log = new QuartzLog();
log.setJobName(quartzJob.getJobName());
@ -67,25 +64,29 @@ public class ExecutionJob extends QuartzJobBean {
log.setCronExpression(quartzJob.getCronExpression());
try {
// 执行任务
logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName());
System.out.println("--------------------------------------------------------------");
System.out.println("任务开始执行,任务名称:" + quartzJob.getJobName());
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
quartzJob.getParams());
Future<?> future = EXECUTOR.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
redisUtils.set(quartzJob.getUuid(), true);
// 任务状态
log.setIsSuccess(true);
logger.info("任务执行完毕,任务名称:{} 总共耗时:{} 毫秒", quartzJob.getJobName(), times);
System.out.println("任务执行完毕,任务名称:" + quartzJob.getJobName() + ", 执行时间:" + times + "毫秒");
System.out.println("--------------------------------------------------------------");
// 判断是否存在子任务
if(quartzJob.getSubTask() != null){
String[] tasks = quartzJob.getSubTask().split("[,]");
for (String id : tasks) {
quartzJobService.execution(quartzJobService.findById(Long.parseLong(id)));
}
// 执行子任务
quartzJobService.executionSubJob(tasks);
}
} catch (Exception e) {
logger.error("任务执行失败,任务名称:{}" + quartzJob.getJobName(), e);
redisUtils.set(quartzJob.getUuid(), false);
System.out.println("任务执行失败,任务名称:" + quartzJob.getJobName());
System.out.println("--------------------------------------------------------------");
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// 任务状态 0成功 1失败

View File

@ -477,7 +477,7 @@ CREATE TABLE `sys_quartz_job` (
-- Records of sys_quartz_job
-- ----------------------------
BEGIN;
INSERT INTO `sys_quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试多参使用json', NULL, NULL, NULL, NULL, NULL, 'admin', '2019-08-22 14:08:29', '2020-05-05 17:26:19');
INSERT INTO `sys_quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试多参使用json', '测试', NULL, NULL, NULL, NULL, 'admin', '2019-08-22 14:08:29', '2020-05-05 17:26:19');
INSERT INTO `sys_quartz_job` VALUES (3, 'testTask', '0/5 * * * * ?', b'1', '测试', 'run', '', '不带参测试', 'Zheng Jie', '', '2,6', b'1', NULL, 'admin', '2019-09-26 16:44:39', '2020-05-05 20:45:39');
INSERT INTO `sys_quartz_job` VALUES (5, 'Test', '0/5 * * * * ?', b'1', '任务告警测试', 'run', NULL, '测试', 'test', '', NULL, b'1', 'admin', 'admin', '2020-05-05 20:32:41', '2020-05-05 20:36:13');
INSERT INTO `sys_quartz_job` VALUES (6, 'testTask', '0/5 * * * * ?', b'1', '测试3', 'run2', NULL, '测试3', 'Zheng Jie', '', NULL, b'1', 'admin', 'admin', '2020-05-05 20:35:41', '2020-05-05 20:36:07');