1. 完成 Job 的 CRUD 功能
parent
bc1504d991
commit
f60855faa0
|
@ -1,48 +1,48 @@
|
||||||
package com.ruoyi.quartz.config;
|
package com.ruoyi.quartz.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务配置
|
* 定时任务配置
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class ScheduleConfig {
|
public class ScheduleConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
|
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
|
||||||
SchedulerFactoryBean factory = new SchedulerFactoryBean();
|
SchedulerFactoryBean factory = new SchedulerFactoryBean();
|
||||||
factory.setDataSource(dataSource);
|
factory.setDataSource(dataSource);
|
||||||
|
|
||||||
// quartz参数
|
// quartz参数
|
||||||
Properties prop = new Properties();
|
Properties prop = new Properties();
|
||||||
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
|
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
|
||||||
prop.put("org.quartz.scheduler.instanceId", "AUTO");
|
prop.put("org.quartz.scheduler.instanceId", "AUTO");
|
||||||
// 集群配置
|
// 集群配置
|
||||||
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
||||||
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
|
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
|
||||||
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
|
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
|
||||||
|
|
||||||
// sqlserver 启用
|
// sqlserver 启用
|
||||||
// prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
|
// prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
|
||||||
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
|
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
|
||||||
factory.setQuartzProperties(prop);
|
factory.setQuartzProperties(prop);
|
||||||
|
|
||||||
factory.setSchedulerName("RuoyiScheduler");
|
factory.setSchedulerName("RuoyiScheduler");
|
||||||
// 延时启动
|
// 延时启动
|
||||||
factory.setStartupDelay(1);
|
factory.setStartupDelay(1);
|
||||||
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
|
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
|
||||||
// 可选,QuartzScheduler
|
// 可选,QuartzScheduler
|
||||||
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
|
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
|
||||||
factory.setOverwriteExistingJobs(true);
|
factory.setOverwriteExistingJobs(true);
|
||||||
|
|
||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,85 +1,64 @@
|
||||||
package com.ruoyi.quartz.controller;
|
package com.ruoyi.quartz.controller;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.quartz.domain.SysJobLog;
|
import com.ruoyi.quartz.domain.SysJobLog;
|
||||||
import com.ruoyi.quartz.service.ISysJobLogService;
|
import com.ruoyi.quartz.service.ISysJobLogService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调度日志操作处理
|
* 调度日志操作处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/monitor/jobLog")
|
@RequestMapping("/monitor/jobLog")
|
||||||
public class SysJobLogController extends BaseController {
|
public class SysJobLogController extends BaseController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysJobLogService jobLogService;
|
private ISysJobLogService jobLogService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询定时任务调度日志列表
|
* 查询定时任务调度日志列表
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:list')")
|
@PreAuthorize("@ss.hasPermi('monitor:job:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(SysJobLog sysJobLog) {
|
public TableDataInfo list(SysJobLog sysJobLog) {
|
||||||
startPage();
|
startPage();
|
||||||
List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
|
List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出定时任务调度日志列表
|
* 导出定时任务调度日志列表
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:export')")
|
@PreAuthorize("@ss.hasPermi('monitor:job:export')")
|
||||||
@Log(title = "任务调度日志", businessType = BusinessType.EXPORT)
|
@Log(title = "任务调度日志", businessType = BusinessType.EXPORT)
|
||||||
@GetMapping("/export")
|
@GetMapping("/export")
|
||||||
public AjaxResult export(SysJobLog sysJobLog) {
|
public AjaxResult export(SysJobLog sysJobLog) {
|
||||||
List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
|
List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
|
||||||
ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
|
ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
|
||||||
return util.exportExcel(list, "调度日志");
|
return util.exportExcel(list, "调度日志");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据调度编号获取详细信息
|
* 根据调度编号获取详细信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:query')")
|
@PreAuthorize("@ss.hasPermi('monitor:job:query')")
|
||||||
@GetMapping(value = "/{configId}")
|
@GetMapping(value = "/{configId}")
|
||||||
public AjaxResult getInfo(@PathVariable Long jobLogId) {
|
public AjaxResult getInfo(@PathVariable Long jobLogId) {
|
||||||
return AjaxResult.success(jobLogService.selectJobLogById(jobLogId));
|
return AjaxResult.success(jobLogService.selectJobLogById(jobLogId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 删除定时任务调度日志
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:remove')")
|
|
||||||
@Log(title = "定时任务调度日志", businessType = BusinessType.DELETE)
|
|
||||||
@DeleteMapping("/{jobLogIds}")
|
|
||||||
public AjaxResult remove(@PathVariable Long[] jobLogIds) {
|
|
||||||
return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空定时任务调度日志
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:remove')")
|
|
||||||
@Log(title = "调度日志", businessType = BusinessType.CLEAN)
|
|
||||||
@DeleteMapping("/clean")
|
|
||||||
public AjaxResult clean() {
|
|
||||||
jobLogService.cleanJobLog();
|
|
||||||
return AjaxResult.success();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +1,54 @@
|
||||||
package com.ruoyi.quartz.service.impl;
|
package com.ruoyi.quartz.service.impl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.ruoyi.quartz.domain.SysJobLog;
|
import com.ruoyi.quartz.domain.SysJobLog;
|
||||||
import com.ruoyi.quartz.mapper.SysJobLogMapper;
|
import com.ruoyi.quartz.mapper.SysJobLogMapper;
|
||||||
import com.ruoyi.quartz.service.ISysJobLogService;
|
import com.ruoyi.quartz.service.ISysJobLogService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务调度日志信息 服务层
|
* 定时任务调度日志信息 服务层
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SysJobLogServiceImpl implements ISysJobLogService {
|
public class SysJobLogServiceImpl implements ISysJobLogService {
|
||||||
@Autowired
|
|
||||||
private SysJobLogMapper jobLogMapper;
|
@Autowired
|
||||||
|
private SysJobLogMapper jobLogMapper;
|
||||||
/**
|
|
||||||
* 获取quartz调度器日志的计划任务
|
/**
|
||||||
*
|
* 获取quartz调度器日志的计划任务
|
||||||
* @param jobLog 调度日志信息
|
*
|
||||||
* @return 调度任务日志集合
|
* @param jobLog 调度日志信息
|
||||||
*/
|
* @return 调度任务日志集合
|
||||||
@Override
|
*/
|
||||||
public List<SysJobLog> selectJobLogList(SysJobLog jobLog) {
|
@Override
|
||||||
return jobLogMapper.selectJobLogList(jobLog);
|
public List<SysJobLog> selectJobLogList(SysJobLog jobLog) {
|
||||||
}
|
return jobLogMapper.selectJobLogList(jobLog);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 通过调度任务日志ID查询调度信息
|
/**
|
||||||
*
|
* 通过调度任务日志ID查询调度信息
|
||||||
* @param jobLogId 调度任务日志ID
|
*
|
||||||
* @return 调度任务日志对象信息
|
* @param jobLogId 调度任务日志ID
|
||||||
*/
|
* @return 调度任务日志对象信息
|
||||||
@Override
|
*/
|
||||||
public SysJobLog selectJobLogById(Long jobLogId) {
|
@Override
|
||||||
return jobLogMapper.selectJobLogById(jobLogId);
|
public SysJobLog selectJobLogById(Long jobLogId) {
|
||||||
}
|
return jobLogMapper.selectJobLogById(jobLogId);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 新增任务日志
|
/**
|
||||||
*
|
* 新增任务日志
|
||||||
* @param jobLog 调度日志信息
|
*
|
||||||
*/
|
* @param jobLog 调度日志信息
|
||||||
@Override
|
*/
|
||||||
public void addJobLog(SysJobLog jobLog) {
|
@Override
|
||||||
jobLogMapper.insertJobLog(jobLog);
|
public void addJobLog(SysJobLog jobLog) {
|
||||||
}
|
jobLogMapper.insertJobLog(jobLog);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 批量删除调度日志信息
|
}
|
||||||
*
|
|
||||||
* @param logIds 需要删除的数据ID
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int deleteJobLogByIds(Long[] logIds) {
|
|
||||||
return jobLogMapper.deleteJobLogByIds(logIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除任务日志
|
|
||||||
*
|
|
||||||
* @param jobId 调度日志ID
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int deleteJobLogById(Long jobId) {
|
|
||||||
return jobLogMapper.deleteJobLogById(jobId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空任务日志
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void cleanJobLog() {
|
|
||||||
jobLogMapper.cleanJobLog();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +1,97 @@
|
||||||
package com.ruoyi.quartz.util;
|
package com.ruoyi.quartz.util;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobExecutionException;
|
import org.quartz.JobExecutionException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.ScheduleConstants;
|
import com.ruoyi.common.constant.ScheduleConstants;
|
||||||
import com.ruoyi.common.utils.ExceptionUtil;
|
import com.ruoyi.common.utils.ExceptionUtil;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
import com.ruoyi.quartz.domain.SysJob;
|
||||||
import com.ruoyi.quartz.domain.SysJobLog;
|
import com.ruoyi.quartz.domain.SysJobLog;
|
||||||
import com.ruoyi.quartz.service.ISysJobLogService;
|
import com.ruoyi.quartz.service.ISysJobLogService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 抽象quartz调用
|
* 抽象quartz调用
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractQuartzJob implements Job {
|
public abstract class AbstractQuartzJob implements Job {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
|
private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 线程本地变量
|
* 线程本地变量
|
||||||
*/
|
*/
|
||||||
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
|
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||||
SysJob sysJob = new SysJob();
|
SysJob sysJob = new SysJob();
|
||||||
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
|
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
|
||||||
try {
|
try {
|
||||||
before(context, sysJob);
|
before(context, sysJob);
|
||||||
if (sysJob != null) {
|
if (sysJob != null) {
|
||||||
doExecute(context, sysJob);
|
doExecute(context, sysJob);
|
||||||
}
|
}
|
||||||
after(context, sysJob, null);
|
after(context, sysJob, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("任务执行异常 - :", e);
|
log.error("任务执行异常 - :", e);
|
||||||
after(context, sysJob, e);
|
after(context, sysJob, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行前
|
* 执行前
|
||||||
*
|
*
|
||||||
* @param context 工作执行上下文对象
|
* @param context 工作执行上下文对象
|
||||||
* @param sysJob 系统计划任务
|
* @param sysJob 系统计划任务
|
||||||
*/
|
*/
|
||||||
protected void before(JobExecutionContext context, SysJob sysJob) {
|
protected void before(JobExecutionContext context, SysJob sysJob) {
|
||||||
threadLocal.set(new Date());
|
threadLocal.set(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行后
|
* 执行后
|
||||||
*
|
*
|
||||||
* @param context 工作执行上下文对象
|
* @param context 工作执行上下文对象
|
||||||
* @param sysJob 系统计划任务
|
* @param sysJob 系统计划任务
|
||||||
*/
|
*/
|
||||||
protected void after(JobExecutionContext context, SysJob sysJob, Exception e) {
|
protected void after(JobExecutionContext context, SysJob sysJob, Exception e) {
|
||||||
Date startTime = threadLocal.get();
|
Date startTime = threadLocal.get();
|
||||||
threadLocal.remove();
|
threadLocal.remove();
|
||||||
|
|
||||||
final SysJobLog sysJobLog = new SysJobLog();
|
final SysJobLog sysJobLog = new SysJobLog();
|
||||||
sysJobLog.setJobName(sysJob.getJobName());
|
sysJobLog.setJobName(sysJob.getJobName());
|
||||||
sysJobLog.setJobGroup(sysJob.getJobGroup());
|
sysJobLog.setJobGroup(sysJob.getJobGroup());
|
||||||
sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
|
sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
|
||||||
sysJobLog.setStartTime(startTime);
|
sysJobLog.setStartTime(startTime);
|
||||||
sysJobLog.setStopTime(new Date());
|
sysJobLog.setStopTime(new Date());
|
||||||
long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
|
long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
|
||||||
sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
|
sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
sysJobLog.setStatus(Constants.FAIL);
|
sysJobLog.setStatus(Constants.FAIL);
|
||||||
String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
|
String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
|
||||||
sysJobLog.setExceptionInfo(errorMsg);
|
sysJobLog.setExceptionInfo(errorMsg);
|
||||||
} else {
|
} else {
|
||||||
sysJobLog.setStatus(Constants.SUCCESS);
|
sysJobLog.setStatus(Constants.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入数据库当中
|
// 写入数据库当中
|
||||||
SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
|
SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行方法,由子类重载
|
* 执行方法,由子类重载
|
||||||
*
|
*
|
||||||
* @param context 工作执行上下文对象
|
* @param context 工作执行上下文对象
|
||||||
* @param sysJob 系统计划任务
|
* @param sysJob 系统计划任务
|
||||||
* @throws Exception 执行过程中的异常
|
* @throws Exception 执行过程中的异常
|
||||||
*/
|
*/
|
||||||
protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
|
protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
|
||||||
}
|
}
|
|
@ -1,44 +1,44 @@
|
||||||
package com.ruoyi.quartz.util;
|
package com.ruoyi.quartz.util;
|
||||||
|
|
||||||
import org.quartz.CronScheduleBuilder;
|
import org.quartz.CronScheduleBuilder;
|
||||||
import org.quartz.CronTrigger;
|
import org.quartz.CronTrigger;
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobBuilder;
|
import org.quartz.JobBuilder;
|
||||||
import org.quartz.JobDetail;
|
import org.quartz.JobDetail;
|
||||||
import org.quartz.JobKey;
|
import org.quartz.JobKey;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.quartz.SchedulerException;
|
import org.quartz.SchedulerException;
|
||||||
import org.quartz.TriggerBuilder;
|
import org.quartz.TriggerBuilder;
|
||||||
import org.quartz.TriggerKey;
|
import org.quartz.TriggerKey;
|
||||||
import com.ruoyi.common.constant.ScheduleConstants;
|
import com.ruoyi.common.constant.ScheduleConstants;
|
||||||
import com.ruoyi.common.exception.job.TaskException;
|
import com.ruoyi.common.exception.job.TaskException;
|
||||||
import com.ruoyi.common.exception.job.TaskException.Code;
|
import com.ruoyi.common.exception.job.TaskException.Code;
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
import com.ruoyi.quartz.domain.SysJob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务工具类
|
* 定时任务工具类
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
public class ScheduleUtils {
|
public class ScheduleUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置定时任务策略
|
* 设置定时任务策略
|
||||||
*/
|
*/
|
||||||
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
|
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
|
||||||
throws TaskException {
|
throws TaskException {
|
||||||
switch (job.getMisfirePolicy()) {
|
switch (job.getMisfirePolicy()) {
|
||||||
case ScheduleConstants.MISFIRE_DEFAULT:
|
case ScheduleConstants.MISFIRE_DEFAULT:
|
||||||
return cb;
|
return cb;
|
||||||
case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
|
case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
|
||||||
return cb.withMisfireHandlingInstructionIgnoreMisfires();
|
return cb.withMisfireHandlingInstructionIgnoreMisfires();
|
||||||
case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
|
case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
|
||||||
return cb.withMisfireHandlingInstructionFireAndProceed();
|
return cb.withMisfireHandlingInstructionFireAndProceed();
|
||||||
case ScheduleConstants.MISFIRE_DO_NOTHING:
|
case ScheduleConstants.MISFIRE_DO_NOTHING:
|
||||||
return cb.withMisfireHandlingInstructionDoNothing();
|
return cb.withMisfireHandlingInstructionDoNothing();
|
||||||
default:
|
default:
|
||||||
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
|
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
|
||||||
+ "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
|
+ "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,132 +0,0 @@
|
||||||
package com.ruoyi.quartz.controller;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.quartz.SchedulerException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import com.ruoyi.common.annotation.Log;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
|
||||||
import com.ruoyi.common.exception.job.TaskException;
|
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
|
||||||
import com.ruoyi.quartz.service.ISysJobService;
|
|
||||||
import com.ruoyi.quartz.util.CronUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调度任务信息操作处理
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/monitor/job")
|
|
||||||
public class SysJobController extends BaseController {
|
|
||||||
@Autowired
|
|
||||||
private ISysJobService jobService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询定时任务列表
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:list')")
|
|
||||||
@GetMapping("/list")
|
|
||||||
public TableDataInfo list(SysJob sysJob) {
|
|
||||||
startPage();
|
|
||||||
List<SysJob> list = jobService.selectJobList(sysJob);
|
|
||||||
return getDataTable(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出定时任务列表
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:export')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.EXPORT)
|
|
||||||
@GetMapping("/export")
|
|
||||||
public AjaxResult export(SysJob sysJob) {
|
|
||||||
List<SysJob> list = jobService.selectJobList(sysJob);
|
|
||||||
ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
|
|
||||||
return util.exportExcel(list, "定时任务");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取定时任务详细信息
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:query')")
|
|
||||||
@GetMapping(value = "/{jobId}")
|
|
||||||
public AjaxResult getInfo(@PathVariable("jobId") Long jobId) {
|
|
||||||
return AjaxResult.success(jobService.selectJobById(jobId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增定时任务
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:add')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.INSERT)
|
|
||||||
@PostMapping
|
|
||||||
public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException {
|
|
||||||
if (!CronUtils.isValid(sysJob.getCronExpression())) {
|
|
||||||
return AjaxResult.error("cron表达式不正确");
|
|
||||||
}
|
|
||||||
sysJob.setCreateBy(SecurityUtils.getUsername());
|
|
||||||
return toAjax(jobService.insertJob(sysJob));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改定时任务
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:edit')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
|
||||||
@PutMapping
|
|
||||||
public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException {
|
|
||||||
if (!CronUtils.isValid(sysJob.getCronExpression())) {
|
|
||||||
return AjaxResult.error("cron表达式不正确");
|
|
||||||
}
|
|
||||||
sysJob.setUpdateBy(SecurityUtils.getUsername());
|
|
||||||
return toAjax(jobService.updateJob(sysJob));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时任务状态修改
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
|
||||||
@PutMapping("/changeStatus")
|
|
||||||
public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException {
|
|
||||||
SysJob newJob = jobService.selectJobById(job.getJobId());
|
|
||||||
newJob.setStatus(job.getStatus());
|
|
||||||
return toAjax(jobService.changeStatus(newJob));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时任务立即执行一次
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
|
||||||
@PutMapping("/run")
|
|
||||||
public AjaxResult run(@RequestBody SysJob job) throws SchedulerException {
|
|
||||||
jobService.run(job);
|
|
||||||
return AjaxResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除定时任务
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:job:remove')")
|
|
||||||
@Log(title = "定时任务", businessType = BusinessType.DELETE)
|
|
||||||
@DeleteMapping("/{jobIds}")
|
|
||||||
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException {
|
|
||||||
jobService.deleteJobByIds(jobIds);
|
|
||||||
return AjaxResult.success();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,218 +0,0 @@
|
||||||
package com.ruoyi.quartz.service.impl;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
|
|
||||||
import org.quartz.JobDataMap;
|
|
||||||
import org.quartz.JobKey;
|
|
||||||
import org.quartz.Scheduler;
|
|
||||||
import org.quartz.SchedulerException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import com.ruoyi.common.constant.ScheduleConstants;
|
|
||||||
import com.ruoyi.common.exception.job.TaskException;
|
|
||||||
import com.ruoyi.quartz.domain.SysJob;
|
|
||||||
import com.ruoyi.quartz.mapper.SysJobMapper;
|
|
||||||
import com.ruoyi.quartz.service.ISysJobService;
|
|
||||||
import com.ruoyi.quartz.util.CronUtils;
|
|
||||||
import com.ruoyi.quartz.util.ScheduleUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时任务调度信息 服务层
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class SysJobServiceImpl implements ISysJobService {
|
|
||||||
@Autowired
|
|
||||||
private Scheduler scheduler;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SysJobMapper jobMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取quartz调度器的计划任务列表
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<SysJob> selectJobList(SysJob job) {
|
|
||||||
return jobMapper.selectJobList(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过调度任务ID查询调度信息
|
|
||||||
*
|
|
||||||
* @param jobId 调度任务ID
|
|
||||||
* @return 调度任务对象信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SysJob selectJobById(Long jobId) {
|
|
||||||
return jobMapper.selectJobById(jobId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 暂停任务
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int pauseJob(SysJob job) throws SchedulerException {
|
|
||||||
Long jobId = job.getJobId();
|
|
||||||
String jobGroup = job.getJobGroup();
|
|
||||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
|
||||||
int rows = jobMapper.updateJob(job);
|
|
||||||
if (rows > 0) {
|
|
||||||
scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复任务
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int resumeJob(SysJob job) throws SchedulerException {
|
|
||||||
Long jobId = job.getJobId();
|
|
||||||
String jobGroup = job.getJobGroup();
|
|
||||||
job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
|
|
||||||
int rows = jobMapper.updateJob(job);
|
|
||||||
if (rows > 0) {
|
|
||||||
scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除任务后,所对应的trigger也将被删除
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int deleteJob(SysJob job) throws SchedulerException {
|
|
||||||
Long jobId = job.getJobId();
|
|
||||||
String jobGroup = job.getJobGroup();
|
|
||||||
int rows = jobMapper.deleteJobById(jobId);
|
|
||||||
if (rows > 0) {
|
|
||||||
scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量删除调度信息
|
|
||||||
*
|
|
||||||
* @param jobIds 需要删除的任务ID
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void deleteJobByIds(Long[] jobIds) throws SchedulerException {
|
|
||||||
for (Long jobId : jobIds) {
|
|
||||||
SysJob job = jobMapper.selectJobById(jobId);
|
|
||||||
deleteJob(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 任务调度状态修改
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int changeStatus(SysJob job) throws SchedulerException {
|
|
||||||
int rows = 0;
|
|
||||||
String status = job.getStatus();
|
|
||||||
if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) {
|
|
||||||
rows = resumeJob(job);
|
|
||||||
} else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) {
|
|
||||||
rows = pauseJob(job);
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 立即运行任务
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void run(SysJob job) throws SchedulerException {
|
|
||||||
Long jobId = job.getJobId();
|
|
||||||
String jobGroup = job.getJobGroup();
|
|
||||||
SysJob properties = selectJobById(job.getJobId());
|
|
||||||
// 参数
|
|
||||||
JobDataMap dataMap = new JobDataMap();
|
|
||||||
dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
|
|
||||||
scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增任务
|
|
||||||
*
|
|
||||||
* @param job 调度信息 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int insertJob(SysJob job) throws SchedulerException, TaskException {
|
|
||||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
|
||||||
int rows = jobMapper.insertJob(job);
|
|
||||||
if (rows > 0) {
|
|
||||||
ScheduleUtils.createScheduleJob(scheduler, job);
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新任务的时间表达式
|
|
||||||
*
|
|
||||||
* @param job 调度信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public int updateJob(SysJob job) throws SchedulerException, TaskException {
|
|
||||||
SysJob properties = selectJobById(job.getJobId());
|
|
||||||
int rows = jobMapper.updateJob(job);
|
|
||||||
if (rows > 0) {
|
|
||||||
updateSchedulerJob(job, properties.getJobGroup());
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新任务
|
|
||||||
*
|
|
||||||
* @param job 任务对象
|
|
||||||
* @param jobGroup 任务组名
|
|
||||||
*/
|
|
||||||
public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException {
|
|
||||||
Long jobId = job.getJobId();
|
|
||||||
// 判断是否存在
|
|
||||||
JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
|
|
||||||
if (scheduler.checkExists(jobKey)) {
|
|
||||||
// 防止创建时存在数据问题 先移除,然后在执行创建操作
|
|
||||||
scheduler.deleteJob(jobKey);
|
|
||||||
}
|
|
||||||
ScheduleUtils.createScheduleJob(scheduler, job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验cron表达式是否有效
|
|
||||||
*
|
|
||||||
* @param cronExpression 表达式
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean checkCronExpressionIsValid(String cronExpression) {
|
|
||||||
return CronUtils.isValid(cronExpression);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
package com.ruoyi.quartz.util;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.quartz.CronExpression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cron表达式工具类
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
public class CronUtils {
|
|
||||||
/**
|
|
||||||
* 返回一个布尔值代表一个给定的Cron表达式的有效性
|
|
||||||
*
|
|
||||||
* @param cronExpression Cron表达式
|
|
||||||
* @return boolean 表达式是否有效
|
|
||||||
*/
|
|
||||||
public static boolean isValid(String cronExpression) {
|
|
||||||
return CronExpression.isValidExpression(cronExpression);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回一个字符串值,表示该消息无效Cron表达式给出有效性
|
|
||||||
*
|
|
||||||
* @param cronExpression Cron表达式
|
|
||||||
* @return String 无效时返回表达式错误描述,如果有效返回null
|
|
||||||
*/
|
|
||||||
public static String getInvalidMessage(String cronExpression) {
|
|
||||||
try {
|
|
||||||
new CronExpression(cronExpression);
|
|
||||||
return null;
|
|
||||||
} catch (ParseException pe) {
|
|
||||||
return pe.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回下一个执行时间根据给定的Cron表达式
|
|
||||||
*
|
|
||||||
* @param cronExpression Cron表达式
|
|
||||||
* @return Date 下次Cron表达式执行时间
|
|
||||||
*/
|
|
||||||
public static Date getNextExecution(String cronExpression) {
|
|
||||||
try {
|
|
||||||
CronExpression cron = new CronExpression(cronExpression);
|
|
||||||
return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new IllegalArgumentException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -46,35 +46,30 @@ export function delJob(jobId) {
|
||||||
// 导出定时任务调度
|
// 导出定时任务调度
|
||||||
export function exportJob(query) {
|
export function exportJob(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/infra/job/export',
|
url: '/infra/job/export-excel',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query,
|
||||||
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务状态修改
|
// 任务状态修改
|
||||||
export function changeJobStatus(jobId, status) {
|
export function updateJobStatus(jobId, status) {
|
||||||
const data = {
|
|
||||||
jobId,
|
|
||||||
status
|
|
||||||
}
|
|
||||||
return request({
|
return request({
|
||||||
url: '/monitor/job/changeStatus',
|
url: '/infra/job/update-status',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
headers:{
|
||||||
|
'Content-type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
data: 'id=' + jobId + "&status=" + status,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 定时任务立即执行一次
|
// 定时任务立即执行一次
|
||||||
export function runJob(jobId, jobGroup) {
|
export function runJob(jobId) {
|
||||||
const data = {
|
|
||||||
jobId,
|
|
||||||
jobGroup
|
|
||||||
}
|
|
||||||
return request({
|
return request({
|
||||||
url: '/monitor/job/run',
|
url: '/infra/job/trigger?id=' + jobId,
|
||||||
method: 'put',
|
method: 'put'
|
||||||
data: data
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -100,7 +100,7 @@ export const constantRoutes = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'log',
|
path: 'log',
|
||||||
component: (resolve) => require(['@/views/monitor/job/log'], resolve),
|
component: (resolve) => require(['@/views/infra/job/log'], resolve),
|
||||||
name: 'JobLog',
|
name: 'JobLog',
|
||||||
meta: { title: '调度日志' }
|
meta: { title: '调度日志' }
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,3 +48,13 @@ export const ToolCodegenTemplateTypeEnum = {
|
||||||
TREE: 2, // 树形 CRUD
|
TREE: 2, // 树形 CRUD
|
||||||
SUB: 3, // 主子表 CRUD
|
SUB: 3, // 主子表 CRUD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务状态的枚举
|
||||||
|
*/
|
||||||
|
export const InfJobStatusEnum = {
|
||||||
|
INIT: 0, // 初始化中
|
||||||
|
NORMAL: 1, // 开启运行
|
||||||
|
EXCEPTION: 2, // 异常运行
|
||||||
|
STOP: 3, // 暂停运行
|
||||||
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading" :style="'height:'+ height">
|
<div v-loading="loading" :style="'height:'+ height">
|
||||||
<iframe :src="src" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" />
|
<iframe :src="src" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "Druid",
|
name: "Druid",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
src: process.env.VUE_APP_BASE_API + "/druid/index.html",
|
src: process.env.VUE_APP_BASE_API + "/druid/index.html",
|
||||||
height: document.documentElement.clientHeight - 94.5 + "px;",
|
height: document.documentElement.clientHeight - 94.5 + "px;",
|
||||||
loading: true
|
loading: true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}, 230);
|
}, 230);
|
||||||
const that = this;
|
const that = this;
|
||||||
window.onresize = function temp() {
|
window.onresize = function temp() {
|
||||||
that.height = document.documentElement.clientHeight - 94.5 + "px;";
|
that.height = document.documentElement.clientHeight - 94.5 + "px;";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
|
@ -1,305 +1,308 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
|
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
|
||||||
<el-form-item label="任务名称" prop="name">
|
<el-form-item label="任务名称" prop="name">
|
||||||
<el-input v-model="queryParams.name" placeholder="请输入任务名称" clearable size="small" @keyup.enter.native="handleQuery"/>
|
<el-input v-model="queryParams.name" placeholder="请输入任务名称" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="任务状态" prop="status">
|
<el-form-item label="任务状态" prop="status">
|
||||||
<el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable size="small">
|
<el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable size="small">
|
||||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.INF_JOB_STATUS)"
|
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.INF_JOB_STATUS)"
|
||||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="处理器的名字" prop="handlerName">
|
<el-form-item label="处理器的名字" prop="handlerName">
|
||||||
<el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable size="small" @keyup.enter.native="handleQuery"/>
|
<el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
|
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||||
v-hasPermi="['monitor:job:add']">新增</el-button>
|
v-hasPermi="['infra:job:create']">新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
|
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
|
||||||
v-hasPermi="['monitor:job:export']">导出</el-button>
|
v-hasPermi="['infra:job:export']">导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog"
|
<el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog"
|
||||||
v-hasPermi="['monitor:job:query']">日志</el-button>
|
v-hasPermi="['monitor:job:query']">日志</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="jobList">
|
<el-table v-loading="loading" :data="jobList">
|
||||||
<el-table-column label="任务编号" align="center" prop="id" />
|
<el-table-column label="任务编号" align="center" prop="id" />
|
||||||
<el-table-column label="任务名称" align="center" prop="name" />
|
<el-table-column label="任务名称" align="center" prop="name" />
|
||||||
<el-table-column label="任务状态" align="center" prop="status">
|
<el-table-column label="任务状态" align="center" prop="status">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, scope.row.status) }}</span>
|
<span>{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, scope.row.status) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>>
|
</el-table-column>>
|
||||||
<el-table-column label="处理器的名字" align="center" prop="handlerName" />
|
<el-table-column label="处理器的名字" align="center" prop="handlerName" />
|
||||||
<el-table-column label="处理器的参数" align="center" prop="handlerParam" />
|
<el-table-column label="处理器的参数" align="center" prop="handlerParam" />
|
||||||
<el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
|
<el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
|
||||||
v-hasPermi="['monitor:job:query']">详细</el-button>
|
v-hasPermi="['infra:job:query']">详细</el-button>
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleUpdate(scope.row)"
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['monitor:job:query']">修改</el-button>
|
v-hasPermi="['infra:job:update']">修改</el-button>
|
||||||
<el-button
|
<el-button size="mini" type="text" icon="el-icon-check" @click="handleChangeStatus(scope.row, true)"
|
||||||
size="mini"
|
v-hasPermi="['infra:job:update']">开启</el-button>
|
||||||
type="text"
|
<el-button size="mini" type="text" icon="el-icon-close" @click="handleChangeStatus(scope.row, false)"
|
||||||
icon="el-icon-caret-right"
|
v-hasPermi="['infra:job:update']">暂停</el-button>
|
||||||
@click="handleRun(scope.row)"
|
<el-button size="mini" type="text" icon="el-icon-caret-right" @click="handleRun(scope.row)"
|
||||||
v-hasPermi="['monitor:job:changeStatus']"
|
v-hasPermi="['infra:job:trigger']">执行一次</el-button>
|
||||||
>执行一次</el-button>
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||||
</template>
|
v-hasPermi="['infra:job:delete']">删除</el-button>
|
||||||
</el-table-column>
|
</template>
|
||||||
</el-table>
|
</el-table-column>
|
||||||
<!-- 分页组件 -->
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
<!-- 分页组件 -->
|
||||||
@pagination="getList"/>
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"/>
|
||||||
<!-- 添加或修改定时任务对话框 -->
|
|
||||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
<!-- 添加或修改定时任务对话框 -->
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
<el-form-item label="任务名称" prop="name">
|
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||||
<el-input v-model="form.name" placeholder="请输入任务名称" />
|
<el-form-item label="任务名称" prop="name">
|
||||||
</el-form-item>
|
<el-input v-model="form.name" placeholder="请输入任务名称" />
|
||||||
<el-form-item label="处理器的名字" prop="handlerName">
|
</el-form-item>
|
||||||
<el-input v-model="form.handlerName" placeholder="请输入处理器的名字" v-bind:readonly="form.id !== undefined" />
|
<el-form-item label="处理器的名字" prop="handlerName">
|
||||||
</el-form-item>
|
<el-input v-model="form.handlerName" placeholder="请输入处理器的名字" v-bind:readonly="form.id !== undefined" />
|
||||||
<el-form-item label="处理器的参数" prop="handlerParam">
|
</el-form-item>
|
||||||
<el-input v-model="form.handlerParam" placeholder="请输入处理器的参数" />
|
<el-form-item label="处理器的参数" prop="handlerParam">
|
||||||
</el-form-item>
|
<el-input v-model="form.handlerParam" placeholder="请输入处理器的参数" />
|
||||||
<el-form-item label="CRON 表达式" prop="cronExpression">
|
</el-form-item>
|
||||||
<el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式" />
|
<el-form-item label="CRON 表达式" prop="cronExpression">
|
||||||
</el-form-item>
|
<el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式" />
|
||||||
<el-form-item label="监控超时时间" prop="monitorTimeout">
|
</el-form-item>
|
||||||
<el-input v-model="form.monitorTimeout" placeholder="请输入监控超时时间,单位:毫秒" />
|
<el-form-item label="监控超时时间" prop="monitorTimeout">
|
||||||
</el-form-item>
|
<el-input v-model="form.monitorTimeout" placeholder="请输入监控超时时间,单位:毫秒" />
|
||||||
</el-form>
|
</el-form-item>
|
||||||
<div slot="footer" class="dialog-footer">
|
</el-form>
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="cancel">取 消</el-button>
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
</div>
|
<el-button @click="cancel">取 消</el-button>
|
||||||
</el-dialog>
|
</div>
|
||||||
|
</el-dialog>
|
||||||
<!-- 任务日志详细 -->
|
|
||||||
<el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body>
|
<!-- 任务日志详细 -->
|
||||||
<el-form ref="form" :model="form" label-width="200px" size="mini">
|
<el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body>
|
||||||
<el-row>
|
<el-form ref="form" :model="form" label-width="200px" size="mini">
|
||||||
<el-col :span="24">
|
<el-row>
|
||||||
<el-form-item label="任务编号:">{{ form.id }}</el-form-item>
|
<el-col :span="24">
|
||||||
<el-form-item label="任务名称:">{{ form.name }}</el-form-item>
|
<el-form-item label="任务编号:">{{ form.id }}</el-form-item>
|
||||||
<el-form-item label="任务名称:">{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, form.status) }}</el-form-item>
|
<el-form-item label="任务名称:">{{ form.name }}</el-form-item>
|
||||||
<el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
|
<el-form-item label="任务名称:">{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, form.status) }}</el-form-item>
|
||||||
<el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
|
<el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
|
||||||
<el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item>
|
<el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
|
||||||
<el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeBeginTime) }}</el-form-item>
|
<el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item>
|
||||||
<el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeEndTime) }}</el-form-item>
|
<el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeBeginTime) }}</el-form-item>
|
||||||
<el-form-item label="上一次触发时间:">{{ parseTime(form.firePrevTime) }}</el-form-item>
|
<el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeEndTime) }}</el-form-item>
|
||||||
<el-form-item label="下一次触发时间:">{{ parseTime(form.fireNextTime) }}</el-form-item>
|
<el-form-item label="上一次触发时间:">{{ parseTime(form.firePrevTime) }}</el-form-item>
|
||||||
<el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item>
|
<el-form-item label="下一次触发时间:">{{ parseTime(form.fireNextTime) }}</el-form-item>
|
||||||
</el-col>
|
<el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item>
|
||||||
</el-row>
|
</el-col>
|
||||||
</el-form>
|
</el-row>
|
||||||
<div slot="footer" class="dialog-footer">
|
</el-form>
|
||||||
<el-button @click="openView = false">关 闭</el-button>
|
<div slot="footer" class="dialog-footer">
|
||||||
</div>
|
<el-button @click="openView = false">关 闭</el-button>
|
||||||
</el-dialog>
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
|
||||||
</template>
|
</div>
|
||||||
|
</template>
|
||||||
<script>
|
|
||||||
import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, changeJobStatus } from "@/api/monitor/job";
|
<script>
|
||||||
|
import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, updateJobStatus } from "@/api/infra/job";
|
||||||
export default {
|
import { InfJobStatusEnum } from "@/utils/constants";
|
||||||
name: "Job",
|
|
||||||
data() {
|
export default {
|
||||||
return {
|
name: "Job",
|
||||||
// 遮罩层
|
data() {
|
||||||
loading: true,
|
return {
|
||||||
// 显示搜索条件
|
// 遮罩层
|
||||||
showSearch: true,
|
loading: true,
|
||||||
// 总条数
|
// 显示搜索条件
|
||||||
total: 0,
|
showSearch: true,
|
||||||
// 定时任务表格数据
|
// 总条数
|
||||||
jobList: [],
|
total: 0,
|
||||||
// 弹出层标题
|
// 定时任务表格数据
|
||||||
title: "",
|
jobList: [],
|
||||||
// 是否显示弹出层
|
// 弹出层标题
|
||||||
open: false,
|
title: "",
|
||||||
// 是否显示详细弹出层
|
// 是否显示弹出层
|
||||||
openView: false,
|
open: false,
|
||||||
// 状态字典
|
// 是否显示详细弹出层
|
||||||
statusOptions: [],
|
openView: false,
|
||||||
// 查询参数
|
// 状态字典
|
||||||
queryParams: {
|
statusOptions: [],
|
||||||
pageNo: 1,
|
// 查询参数
|
||||||
pageSize: 10,
|
queryParams: {
|
||||||
name: undefined,
|
pageNo: 1,
|
||||||
status: undefined,
|
pageSize: 10,
|
||||||
handlerName: undefined
|
name: undefined,
|
||||||
},
|
status: undefined,
|
||||||
// 表单参数
|
handlerName: undefined
|
||||||
form: {},
|
},
|
||||||
// 表单校验
|
// 表单参数
|
||||||
rules: {
|
form: {},
|
||||||
name: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
|
// 表单校验
|
||||||
handlerName: [{ required: true, message: "处理器的名字不能为空", trigger: "blur" }],
|
rules: {
|
||||||
cronExpression: [{ required: true, message: "CRON 表达式不能为空", trigger: "blur" }],
|
name: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
|
||||||
}
|
handlerName: [{ required: true, message: "处理器的名字不能为空", trigger: "blur" }],
|
||||||
};
|
cronExpression: [{ required: true, message: "CRON 表达式不能为空", trigger: "blur" }],
|
||||||
},
|
}
|
||||||
created() {
|
};
|
||||||
this.getList();
|
},
|
||||||
},
|
created() {
|
||||||
methods: {
|
this.getList();
|
||||||
/** 查询定时任务列表 */
|
},
|
||||||
getList() {
|
methods: {
|
||||||
this.loading = true;
|
/** 查询定时任务列表 */
|
||||||
listJob(this.queryParams).then(response => {
|
getList() {
|
||||||
this.jobList = response.data.list;
|
this.loading = true;
|
||||||
this.total = response.data.total;
|
listJob(this.queryParams).then(response => {
|
||||||
this.loading = false;
|
this.jobList = response.data.list;
|
||||||
});
|
this.total = response.data.total;
|
||||||
},
|
this.loading = false;
|
||||||
/** 取消按钮 */
|
});
|
||||||
cancel() {
|
},
|
||||||
this.open = false;
|
/** 取消按钮 */
|
||||||
this.reset();
|
cancel() {
|
||||||
},
|
this.open = false;
|
||||||
/** 表单重置 */
|
this.reset();
|
||||||
reset() {
|
},
|
||||||
this.form = {
|
/** 表单重置 */
|
||||||
id: undefined,
|
reset() {
|
||||||
name: undefined,
|
this.form = {
|
||||||
handlerName: undefined,
|
id: undefined,
|
||||||
handlerParam: undefined,
|
name: undefined,
|
||||||
cronExpression: undefined,
|
handlerName: undefined,
|
||||||
monitorTimeout: undefined,
|
handlerParam: undefined,
|
||||||
};
|
cronExpression: undefined,
|
||||||
this.resetForm("form");
|
monitorTimeout: undefined,
|
||||||
},
|
};
|
||||||
/** 搜索按钮操作 */
|
this.resetForm("form");
|
||||||
handleQuery() {
|
},
|
||||||
this.queryParams.pageNo = 1;
|
/** 搜索按钮操作 */
|
||||||
this.getList();
|
handleQuery() {
|
||||||
},
|
this.queryParams.pageNo = 1;
|
||||||
/** 重置按钮操作 */
|
this.getList();
|
||||||
resetQuery() {
|
},
|
||||||
this.resetForm("queryForm");
|
/** 重置按钮操作 */
|
||||||
this.handleQuery();
|
resetQuery() {
|
||||||
},
|
this.resetForm("queryForm");
|
||||||
// 任务状态修改
|
this.handleQuery();
|
||||||
handleStatusChange(row) {
|
},
|
||||||
let text = row.status === "0" ? "启用" : "停用";
|
/** 立即执行一次 **/
|
||||||
this.$confirm('确认要"' + text + '""' + row.name + '"任务吗?', "警告", {
|
handleRun(row) {
|
||||||
confirmButtonText: "确定",
|
this.$confirm('确认要立即执行一次"' + row.name + '"任务吗?', "警告", {
|
||||||
cancelButtonText: "取消",
|
confirmButtonText: "确定",
|
||||||
type: "warning"
|
cancelButtonText: "取消",
|
||||||
}).then(function() {
|
type: "warning"
|
||||||
return changeJobStatus(row.id, row.status);
|
}).then(function() {
|
||||||
}).then(() => {
|
return runJob(row.id);
|
||||||
this.msgSuccess(text + "成功");
|
}).then(() => {
|
||||||
}).catch(function() {
|
this.msgSuccess("执行成功");
|
||||||
row.status = row.status === "0" ? "1" : "0";
|
})
|
||||||
});
|
},
|
||||||
},
|
/** 任务详细信息 */
|
||||||
/* 立即执行一次 */
|
handleView(row) {
|
||||||
handleRun(row) {
|
getJob(row.id).then(response => {
|
||||||
this.$confirm('确认要立即执行一次"' + row.name + '"任务吗?', "警告", {
|
this.form = response.data;
|
||||||
confirmButtonText: "确定",
|
this.openView = true;
|
||||||
cancelButtonText: "取消",
|
});
|
||||||
type: "warning"
|
},
|
||||||
}).then(function() {
|
/** 任务日志列表查询 */
|
||||||
return runJob(row.id, row.jobGroup);
|
handleJobLog() {
|
||||||
}).then(() => {
|
this.$router.push("/job/log");
|
||||||
this.msgSuccess("执行成功");
|
},
|
||||||
})
|
/** 新增按钮操作 */
|
||||||
},
|
handleAdd() {
|
||||||
/** 任务详细信息 */
|
this.reset();
|
||||||
handleView(row) {
|
this.open = true;
|
||||||
getJob(row.id).then(response => {
|
this.title = "添加任务";
|
||||||
this.form = response.data;
|
},
|
||||||
this.openView = true;
|
/** 修改按钮操作 */
|
||||||
});
|
handleUpdate(row) {
|
||||||
},
|
this.reset();
|
||||||
/** 任务日志列表查询 */
|
const id = row.id;
|
||||||
handleJobLog() {
|
getJob(id).then(response => {
|
||||||
this.$router.push("/job/log");
|
this.form = response.data;
|
||||||
},
|
this.open = true;
|
||||||
/** 新增按钮操作 */
|
this.title = "修改任务";
|
||||||
handleAdd() {
|
});
|
||||||
this.reset();
|
},
|
||||||
this.open = true;
|
/** 提交按钮 */
|
||||||
this.title = "添加任务";
|
submitForm: function() {
|
||||||
},
|
this.$refs["form"].validate(valid => {
|
||||||
/** 修改按钮操作 */
|
if (valid) {
|
||||||
handleUpdate(row) {
|
if (this.form.id !== undefined) {
|
||||||
this.reset();
|
updateJob(this.form).then(response => {
|
||||||
const id = row.id;
|
this.msgSuccess("修改成功");
|
||||||
getJob(id).then(response => {
|
this.open = false;
|
||||||
this.form = response.data;
|
this.getList();
|
||||||
this.open = true;
|
});
|
||||||
this.title = "修改任务";
|
} else {
|
||||||
});
|
addJob(this.form).then(response => {
|
||||||
},
|
this.msgSuccess("新增成功");
|
||||||
/** 提交按钮 */
|
this.open = false;
|
||||||
submitForm: function() {
|
this.getList();
|
||||||
this.$refs["form"].validate(valid => {
|
});
|
||||||
if (valid) {
|
}
|
||||||
if (this.form.id !== undefined) {
|
}
|
||||||
updateJob(this.form).then(response => {
|
});
|
||||||
this.msgSuccess("修改成功");
|
},
|
||||||
this.open = false;
|
/** 删除按钮操作 */
|
||||||
this.getList();
|
handleDelete(row) {
|
||||||
});
|
const ids = row.id;
|
||||||
} else {
|
this.$confirm('是否确认删除定时任务编号为"' + ids + '"的数据项?', "警告", {
|
||||||
addJob(this.form).then(response => {
|
confirmButtonText: "确定",
|
||||||
this.msgSuccess("新增成功");
|
cancelButtonText: "取消",
|
||||||
this.open = false;
|
type: "warning"
|
||||||
this.getList();
|
}).then(function() {
|
||||||
});
|
return delJob(ids);
|
||||||
}
|
}).then(() => {
|
||||||
}
|
this.getList();
|
||||||
});
|
this.msgSuccess("删除成功");
|
||||||
},
|
})
|
||||||
/** 删除按钮操作 */
|
},
|
||||||
handleDelete(row) {
|
/** 更新状态操作 */
|
||||||
const ids = row.id || this.ids;
|
handleChangeStatus(row, open) {
|
||||||
this.$confirm('是否确认删除定时任务编号为"' + ids + '"的数据项?', "警告", {
|
const id = row.id;
|
||||||
confirmButtonText: "确定",
|
let status = open ? InfJobStatusEnum.NORMAL : InfJobStatusEnum.STOP;
|
||||||
cancelButtonText: "取消",
|
let statusStr = open ? '开启' : '关闭';
|
||||||
type: "warning"
|
this.$confirm('是否确认' + statusStr + '定时任务编号为"' + id + '"的数据项?', "警告", {
|
||||||
}).then(function() {
|
confirmButtonText: "确定",
|
||||||
return delJob(ids);
|
cancelButtonText: "取消",
|
||||||
}).then(() => {
|
type: "warning"
|
||||||
this.getList();
|
}).then(function() {
|
||||||
this.msgSuccess("删除成功");
|
return updateJobStatus(id, status);
|
||||||
})
|
}).then(() => {
|
||||||
},
|
this.getList();
|
||||||
/** 导出按钮操作 */
|
this.msgSuccess(statusStr + "成功");
|
||||||
handleExport() {
|
})
|
||||||
const queryParams = this.queryParams;
|
},
|
||||||
this.$confirm("是否确认导出所有定时任务数据项?", "警告", {
|
/** 导出按钮操作 */
|
||||||
confirmButtonText: "确定",
|
handleExport() {
|
||||||
cancelButtonText: "取消",
|
const queryParams = this.queryParams;
|
||||||
type: "warning"
|
this.$confirm("是否确认导出所有定时任务数据项?", "警告", {
|
||||||
}).then(function() {
|
confirmButtonText: "确定",
|
||||||
return exportJob(queryParams);
|
cancelButtonText: "取消",
|
||||||
}).then(response => {
|
type: "warning"
|
||||||
this.download(response.msg);
|
}).then(function() {
|
||||||
})
|
return exportJob(queryParams);
|
||||||
}
|
}).then(response => {
|
||||||
}
|
this.downloadExcel(response, '定时任务.xls');
|
||||||
};
|
})
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,210 +1,210 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>CPU</span></div>
|
<div slot="header"><span>CPU</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="is-leaf"><div class="cell">属性</div></th>
|
<th class="is-leaf"><div class="cell">属性</div></th>
|
||||||
<th class="is-leaf"><div class="cell">值</div></th>
|
<th class="is-leaf"><div class="cell">值</div></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">核心数</div></td>
|
<td><div class="cell">核心数</div></td>
|
||||||
<td><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
|
<td><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">用户使用率</div></td>
|
<td><div class="cell">用户使用率</div></td>
|
||||||
<td><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
|
<td><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">系统使用率</div></td>
|
<td><div class="cell">系统使用率</div></td>
|
||||||
<td><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
|
<td><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">当前空闲率</div></td>
|
<td><div class="cell">当前空闲率</div></td>
|
||||||
<td><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
|
<td><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>内存</span></div>
|
<div slot="header"><span>内存</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="is-leaf"><div class="cell">属性</div></th>
|
<th class="is-leaf"><div class="cell">属性</div></th>
|
||||||
<th class="is-leaf"><div class="cell">内存</div></th>
|
<th class="is-leaf"><div class="cell">内存</div></th>
|
||||||
<th class="is-leaf"><div class="cell">JVM</div></th>
|
<th class="is-leaf"><div class="cell">JVM</div></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">总内存</div></td>
|
<td><div class="cell">总内存</div></td>
|
||||||
<td><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
|
<td><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">已用内存</div></td>
|
<td><div class="cell">已用内存</div></td>
|
||||||
<td><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
|
<td><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">剩余内存</div></td>
|
<td><div class="cell">剩余内存</div></td>
|
||||||
<td><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
|
<td><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">使用率</div></td>
|
<td><div class="cell">使用率</div></td>
|
||||||
<td><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
|
<td><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
|
<td><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>服务器信息</span>
|
<span>服务器信息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">服务器名称</div></td>
|
<td><div class="cell">服务器名称</div></td>
|
||||||
<td><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
|
<td><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
|
||||||
<td><div class="cell">操作系统</div></td>
|
<td><div class="cell">操作系统</div></td>
|
||||||
<td><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
|
<td><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">服务器IP</div></td>
|
<td><div class="cell">服务器IP</div></td>
|
||||||
<td><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
|
<td><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
|
||||||
<td><div class="cell">系统架构</div></td>
|
<td><div class="cell">系统架构</div></td>
|
||||||
<td><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
|
<td><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>Java虚拟机信息</span>
|
<span>Java虚拟机信息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">Java名称</div></td>
|
<td><div class="cell">Java名称</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
|
||||||
<td><div class="cell">Java版本</div></td>
|
<td><div class="cell">Java版本</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div class="cell">启动时间</div></td>
|
<td><div class="cell">启动时间</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
|
||||||
<td><div class="cell">运行时长</div></td>
|
<td><div class="cell">运行时长</div></td>
|
||||||
<td><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
|
<td><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1"><div class="cell">安装路径</div></td>
|
<td colspan="1"><div class="cell">安装路径</div></td>
|
||||||
<td colspan="3"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
|
<td colspan="3"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1"><div class="cell">项目路径</div></td>
|
<td colspan="1"><div class="cell">项目路径</div></td>
|
||||||
<td colspan="3"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
|
<td colspan="3"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>磁盘状态</span>
|
<span>磁盘状态</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="is-leaf"><div class="cell">盘符路径</div></th>
|
<th class="is-leaf"><div class="cell">盘符路径</div></th>
|
||||||
<th class="is-leaf"><div class="cell">文件系统</div></th>
|
<th class="is-leaf"><div class="cell">文件系统</div></th>
|
||||||
<th class="is-leaf"><div class="cell">盘符类型</div></th>
|
<th class="is-leaf"><div class="cell">盘符类型</div></th>
|
||||||
<th class="is-leaf"><div class="cell">总大小</div></th>
|
<th class="is-leaf"><div class="cell">总大小</div></th>
|
||||||
<th class="is-leaf"><div class="cell">可用大小</div></th>
|
<th class="is-leaf"><div class="cell">可用大小</div></th>
|
||||||
<th class="is-leaf"><div class="cell">已用大小</div></th>
|
<th class="is-leaf"><div class="cell">已用大小</div></th>
|
||||||
<th class="is-leaf"><div class="cell">已用百分比</div></th>
|
<th class="is-leaf"><div class="cell">已用百分比</div></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody v-if="server.sysFiles">
|
<tbody v-if="server.sysFiles">
|
||||||
<tr v-for="sysFile in server.sysFiles">
|
<tr v-for="sysFile in server.sysFiles">
|
||||||
<td><div class="cell">{{ sysFile.dirName }}</div></td>
|
<td><div class="cell">{{ sysFile.dirName }}</div></td>
|
||||||
<td><div class="cell">{{ sysFile.sysTypeName }}</div></td>
|
<td><div class="cell">{{ sysFile.sysTypeName }}</div></td>
|
||||||
<td><div class="cell">{{ sysFile.typeName }}</div></td>
|
<td><div class="cell">{{ sysFile.typeName }}</div></td>
|
||||||
<td><div class="cell">{{ sysFile.total }}</div></td>
|
<td><div class="cell">{{ sysFile.total }}</div></td>
|
||||||
<td><div class="cell">{{ sysFile.free }}</div></td>
|
<td><div class="cell">{{ sysFile.free }}</div></td>
|
||||||
<td><div class="cell">{{ sysFile.used }}</div></td>
|
<td><div class="cell">{{ sysFile.used }}</div></td>
|
||||||
<td><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
|
<td><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getServer } from "@/api/monitor/server";
|
import { getServer } from "@/api/monitor/server";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Server",
|
name: "Server",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 加载层信息
|
// 加载层信息
|
||||||
loading: [],
|
loading: [],
|
||||||
// 服务器信息
|
// 服务器信息
|
||||||
server: []
|
server: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.openLoading();
|
this.openLoading();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询服务器信息 */
|
/** 查询服务器信息 */
|
||||||
getList() {
|
getList() {
|
||||||
getServer().then(response => {
|
getServer().then(response => {
|
||||||
this.server = response.data;
|
this.server = response.data;
|
||||||
this.loading.close();
|
this.loading.close();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 打开加载层
|
// 打开加载层
|
||||||
openLoading() {
|
openLoading() {
|
||||||
this.loading = this.$loading({
|
this.loading = this.$loading({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: "拼命读取中",
|
text: "拼命读取中",
|
||||||
spinner: "el-icon-loading",
|
spinner: "el-icon-loading",
|
||||||
background: "rgba(0, 0, 0, 0.7)"
|
background: "rgba(0, 0, 0, 0.7)"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
File diff suppressed because one or more lines are too long
|
@ -28,4 +28,8 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
|
||||||
return selectList(new QueryWrapper<>());
|
return selectList(new QueryWrapper<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default T selectOne(String field, Object value) {
|
||||||
|
return selectOne(new QueryWrapper<T>().eq(field, value));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,12 @@ import org.quartz.*;
|
||||||
/**
|
/**
|
||||||
* {@link org.quartz.Scheduler} 的管理器,负责创建任务
|
* {@link org.quartz.Scheduler} 的管理器,负责创建任务
|
||||||
*
|
*
|
||||||
|
* 考虑到实现的简洁性,我们使用 jobHandlerName 作为唯一标识,即:
|
||||||
|
* 1. Job 的 {@link JobDetail#getKey()}
|
||||||
|
* 2. Trigger 的 {@link Trigger#getKey()}
|
||||||
|
*
|
||||||
|
* 另外,jobHandlerName 对应到 Spring Bean 的名字,直接调用
|
||||||
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class SchedulerManager {
|
public class SchedulerManager {
|
||||||
|
@ -17,6 +23,15 @@ public class SchedulerManager {
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 Job 到 Quartz 中
|
||||||
|
*
|
||||||
|
* @param jobId 任务编号
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @param jobHandlerParam 任务处理器的参数
|
||||||
|
* @param cronExpression CRON 表达式
|
||||||
|
* @throws SchedulerException 添加异常
|
||||||
|
*/
|
||||||
public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression)
|
public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
// 创建 JobDetail 对象
|
// 创建 JobDetail 对象
|
||||||
|
@ -30,6 +45,14 @@ public class SchedulerManager {
|
||||||
scheduler.scheduleJob(jobDetail, trigger);
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新 Job 到 Quartz
|
||||||
|
*
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @param jobHandlerParam 任务处理器的参数
|
||||||
|
* @param cronExpression CRON 表达式
|
||||||
|
* @throws SchedulerException 更新异常
|
||||||
|
*/
|
||||||
public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression)
|
public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
// 创建新 Trigger 对象
|
// 创建新 Trigger 对象
|
||||||
|
@ -38,19 +61,45 @@ public class SchedulerManager {
|
||||||
scheduler.rescheduleJob(new TriggerKey(jobHandlerName), newTrigger);
|
scheduler.rescheduleJob(new TriggerKey(jobHandlerName), newTrigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 Quartz 中的 Job
|
||||||
|
*
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @throws SchedulerException 删除异常
|
||||||
|
*/
|
||||||
public void deleteJob(String jobHandlerName) throws SchedulerException {
|
public void deleteJob(String jobHandlerName) throws SchedulerException {
|
||||||
scheduler.deleteJob(new JobKey(jobHandlerName));
|
scheduler.deleteJob(new JobKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暂停 Quartz 中的 Job
|
||||||
|
*
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @throws SchedulerException 暂停异常
|
||||||
|
*/
|
||||||
public void pauseJob(String jobHandlerName) throws SchedulerException {
|
public void pauseJob(String jobHandlerName) throws SchedulerException {
|
||||||
scheduler.pauseJob(new JobKey(jobHandlerName));
|
scheduler.pauseJob(new JobKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动 Quartz 中的 Job
|
||||||
|
*
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @throws SchedulerException 启动异常
|
||||||
|
*/
|
||||||
public void resumeJob(String jobHandlerName) throws SchedulerException {
|
public void resumeJob(String jobHandlerName) throws SchedulerException {
|
||||||
scheduler.resumeJob(new JobKey(jobHandlerName));
|
scheduler.resumeJob(new JobKey(jobHandlerName));
|
||||||
scheduler.resumeTrigger(new TriggerKey(jobHandlerName));
|
scheduler.resumeTrigger(new TriggerKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 立即触发一次 Quartz 中的 Job
|
||||||
|
*
|
||||||
|
* @param jobId 任务编号
|
||||||
|
* @param jobHandlerName 任务处理器的名字
|
||||||
|
* @param jobHandlerParam 任务处理器的参数
|
||||||
|
* @throws SchedulerException 触发异常
|
||||||
|
*/
|
||||||
public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam)
|
public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
JobDataMap data = new JobDataMap();
|
JobDataMap data = new JobDataMap();
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.iocoder.dashboard.framework.quartz.core.util;
|
||||||
|
|
||||||
|
import org.quartz.CronExpression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quartz Cron 表达式的工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class CronUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验 CRON 表达式是否有效
|
||||||
|
*
|
||||||
|
* @param cronExpression CRON 表达式
|
||||||
|
* @return 是否有效
|
||||||
|
*/
|
||||||
|
public static boolean isValid(String cronExpression) {
|
||||||
|
return CronExpression.isValidExpression(cronExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,7 +10,9 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
|
||||||
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
|
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -37,30 +39,55 @@ public class InfJobController {
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@ApiOperation("创建定时任务")
|
@ApiOperation("创建定时任务")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:job:create')")
|
@PreAuthorize("@ss.hasPermission('infra:job:create')")
|
||||||
public CommonResult<Long> createJob(@Valid @RequestBody InfJobCreateReqVO createReqVO) {
|
public CommonResult<Long> createJob(@Valid @RequestBody InfJobCreateReqVO createReqVO)
|
||||||
|
throws SchedulerException {
|
||||||
return success(jobService.createJob(createReqVO));
|
return success(jobService.createJob(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@ApiOperation("更新定时任务")
|
@ApiOperation("更新定时任务")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:job:update')")
|
@PreAuthorize("@ss.hasPermission('infra:job:update')")
|
||||||
public CommonResult<Boolean> updateJob(@Valid @RequestBody InfJobUpdateReqVO updateReqVO) {
|
public CommonResult<Boolean> updateJob(@Valid @RequestBody InfJobUpdateReqVO updateReqVO)
|
||||||
|
throws SchedulerException {
|
||||||
jobService.updateJob(updateReqVO);
|
jobService.updateJob(updateReqVO);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update-status")
|
||||||
|
@ApiOperation("更新定时任务的状态")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class),
|
||||||
|
@ApiImplicitParam(name = "status", value = "状态", required = true, example = "1", dataTypeClass = Integer.class),
|
||||||
|
})
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:job:update')")
|
||||||
|
public CommonResult<Boolean> updateJobStatus(@RequestParam(value = "id") Long id, @RequestParam("status") Integer status)
|
||||||
|
throws SchedulerException {
|
||||||
|
jobService.updateJobStatus(id, status);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@ApiOperation("删除定时任务")
|
@ApiOperation("删除定时任务")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
|
||||||
public CommonResult<Boolean> deleteJob(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteJob(@RequestParam("id") Long id)
|
||||||
|
throws SchedulerException {
|
||||||
jobService.deleteJob(id);
|
jobService.deleteJob(id);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/trigger")
|
||||||
|
@ApiOperation("触发定时任务")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:job:trigger')")
|
||||||
|
public CommonResult<Boolean> triggerJob(@RequestParam("id") Long id) throws SchedulerException {
|
||||||
|
jobService.triggerJob(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@ApiOperation("获得定时任务")
|
@ApiOperation("获得定时任务")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||||
public CommonResult<InfJobRespVO> getJob(@RequestParam("id") Long id) {
|
public CommonResult<InfJobRespVO> getJob(@RequestParam("id") Long id) {
|
||||||
InfJobDO job = jobService.getJob(id);
|
InfJobDO job = jobService.getJob(id);
|
||||||
|
|
|
@ -2,13 +2,9 @@ package cn.iocoder.dashboard.modules.infra.dal.dataobject.job;
|
||||||
|
|
||||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum;
|
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.*;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
@ -21,6 +17,9 @@ import java.util.Date;
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class InfJobDO extends BaseDO {
|
public class InfJobDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +44,6 @@ public class InfJobDO extends BaseDO {
|
||||||
/**
|
/**
|
||||||
* 处理器的参数
|
* 处理器的参数
|
||||||
*/
|
*/
|
||||||
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
|
||||||
private String handlerParam;
|
private String handlerParam;
|
||||||
|
|
||||||
// ========== 时间相关字段 ==========
|
// ========== 时间相关字段 ==========
|
||||||
|
|
|
@ -18,6 +18,10 @@ import java.util.List;
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface InfJobMapper extends BaseMapperX<InfJobDO> {
|
public interface InfJobMapper extends BaseMapperX<InfJobDO> {
|
||||||
|
|
||||||
|
default InfJobDO selectByHandlerName(String handlerName) {
|
||||||
|
return selectOne("handler_name", handlerName);
|
||||||
|
}
|
||||||
|
|
||||||
default PageResult<InfJobDO> selectPage(InfJobPageReqVO reqVO) {
|
default PageResult<InfJobDO> selectPage(InfJobPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new QueryWrapperX<InfJobDO>()
|
return selectPage(reqVO, new QueryWrapperX<InfJobDO>()
|
||||||
.likeIfPresent("name", reqVO.getName())
|
.likeIfPresent("name", reqVO.getName())
|
||||||
|
|
|
@ -17,5 +17,10 @@ public interface InfErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 定时任务 1001001000 ==========
|
// ========== 定时任务 1001001000 ==========
|
||||||
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");
|
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");
|
||||||
|
ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1001001001, "定时任务的处理器已经存在");
|
||||||
|
ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1001001002, "只允许修改为开启或者关闭状态");
|
||||||
|
ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1001001003, "定时任务已经处于该状态,无需修改");
|
||||||
|
ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1001001004, "只有开启状态的任务,才可以修改");
|
||||||
|
ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1001001005, "CRON 表达式不正确");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqV
|
||||||
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
|
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
|
||||||
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
|
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
|
||||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
|
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -24,21 +25,36 @@ public interface InfJobService {
|
||||||
* @param createReqVO 创建信息
|
* @param createReqVO 创建信息
|
||||||
* @return 编号
|
* @return 编号
|
||||||
*/
|
*/
|
||||||
Long createJob(@Valid InfJobCreateReqVO createReqVO);
|
Long createJob(@Valid InfJobCreateReqVO createReqVO) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新定时任务
|
* 更新定时任务
|
||||||
*
|
*
|
||||||
* @param updateReqVO 更新信息
|
* @param updateReqVO 更新信息
|
||||||
*/
|
*/
|
||||||
void updateJob(@Valid InfJobUpdateReqVO updateReqVO);
|
void updateJob(@Valid InfJobUpdateReqVO updateReqVO) throws SchedulerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新定时任务的状态
|
||||||
|
*
|
||||||
|
* @param id 任务编号
|
||||||
|
* @param status 状态
|
||||||
|
*/
|
||||||
|
void updateJobStatus(Long id, Integer status) throws SchedulerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发定时任务
|
||||||
|
*
|
||||||
|
* @param id 任务编号
|
||||||
|
*/
|
||||||
|
void triggerJob(Long id) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除定时任务
|
* 删除定时任务
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
*/
|
*/
|
||||||
void deleteJob(Long id);
|
void deleteJob(Long id) throws SchedulerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得定时任务
|
* 获得定时任务
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package cn.iocoder.dashboard.modules.infra.service.job.impl;
|
package cn.iocoder.dashboard.modules.infra.service.job.impl;
|
||||||
|
|
||||||
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
|
|
||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager;
|
||||||
|
import cn.iocoder.dashboard.framework.quartz.core.util.CronUtils;
|
||||||
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
|
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
|
||||||
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
|
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
|
||||||
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
|
import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
|
||||||
|
@ -9,15 +10,20 @@ import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqV
|
||||||
import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
|
import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
|
||||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
|
import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
|
||||||
import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper;
|
import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper;
|
||||||
|
import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum;
|
||||||
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
|
import cn.iocoder.dashboard.modules.infra.service.job.InfJobService;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_NOT_EXISTS;
|
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.*;
|
||||||
|
import static cn.iocoder.dashboard.util.collection.CollectionUtils.containsAny;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务 Service 实现类
|
* 定时任务 Service 实现类
|
||||||
|
@ -31,41 +37,109 @@ public class InfJobServiceImpl implements InfJobService {
|
||||||
@Resource
|
@Resource
|
||||||
private InfJobMapper jobMapper;
|
private InfJobMapper jobMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SchedulerManager schedulerManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createJob(InfJobCreateReqVO createReqVO) {
|
@Transactional
|
||||||
|
public Long createJob(InfJobCreateReqVO createReqVO) throws SchedulerException {
|
||||||
|
validateCronExpression(createReqVO.getCronExpression());
|
||||||
|
// 校验唯一性
|
||||||
|
if (jobMapper.selectByHandlerName(createReqVO.getHandlerName()) != null) {
|
||||||
|
throw exception(JOB_HANDLER_EXISTS);
|
||||||
|
}
|
||||||
// 插入
|
// 插入
|
||||||
InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
|
InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
|
||||||
if (job.getMonitorTimeout() == null) {
|
job.setStatus(InfJobStatusEnum.INIT.getStatus());
|
||||||
job.setMonitorTimeout(0);
|
fillJobMonitorTimeoutEmpty(job);
|
||||||
}
|
|
||||||
jobMapper.insert(job);
|
jobMapper.insert(job);
|
||||||
|
|
||||||
|
// 添加 Job 到 Quartz 中
|
||||||
|
schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression());
|
||||||
|
// 更新
|
||||||
|
InfJobDO updateObj = InfJobDO.builder().id(job.getId()).status(InfJobStatusEnum.NORMAL.getStatus()).build();
|
||||||
|
jobMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
return job.getId();
|
return job.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateJob(InfJobUpdateReqVO updateReqVO) {
|
@Transactional
|
||||||
|
public void updateJob(InfJobUpdateReqVO updateReqVO) throws SchedulerException {
|
||||||
|
validateCronExpression(updateReqVO.getCronExpression());
|
||||||
// 校验存在
|
// 校验存在
|
||||||
this.validateJobExists(updateReqVO.getId());
|
InfJobDO job = this.validateJobExists(updateReqVO.getId());
|
||||||
|
// 只有开启状态,才可以修改.原因是,如果出暂停状态,修改 Quartz Job 时,会导致任务又开始执行
|
||||||
|
if (!job.getStatus().equals(InfJobStatusEnum.NORMAL.getStatus())) {
|
||||||
|
throw exception(JOB_UPDATE_ONLY_NORMAL_STATUS);
|
||||||
|
}
|
||||||
// 更新
|
// 更新
|
||||||
InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO);
|
InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO);
|
||||||
if (updateObj.getMonitorTimeout() == null) {
|
fillJobMonitorTimeoutEmpty(updateObj);
|
||||||
updateObj.setMonitorTimeout(0);
|
|
||||||
}
|
|
||||||
jobMapper.updateById(updateObj);
|
jobMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
// 更新 Job 到 Quartz 中
|
||||||
|
schedulerManager.updateJob(job.getHandlerName(), updateReqVO.getHandlerParam(), updateReqVO.getCronExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteJob(Long id) {
|
@Transactional
|
||||||
|
public void updateJobStatus(Long id, Integer status) throws SchedulerException {
|
||||||
|
// 校验 status
|
||||||
|
if (!containsAny(status, InfJobStatusEnum.NORMAL.getStatus(), InfJobStatusEnum.STOP.getStatus())) {
|
||||||
|
throw exception(JOB_CHANGE_STATUS_INVALID);
|
||||||
|
}
|
||||||
// 校验存在
|
// 校验存在
|
||||||
this.validateJobExists(id);
|
InfJobDO job = this.validateJobExists(id);
|
||||||
// 更新
|
// 校验是否已经为当前状态
|
||||||
jobMapper.deleteById(id);
|
if (job.getStatus().equals(status)) {
|
||||||
|
throw exception(JOB_CHANGE_STATUS_EQUALS);
|
||||||
|
}
|
||||||
|
// 更新 Job 状态
|
||||||
|
InfJobDO updateObj = InfJobDO.builder().id(id).status(status).build();
|
||||||
|
jobMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
// 更新状态 Job 到 Quartz 中
|
||||||
|
if (InfJobStatusEnum.NORMAL.getStatus().equals(status)) { // 开启
|
||||||
|
schedulerManager.resumeJob(job.getHandlerName());
|
||||||
|
} else { // 暂停
|
||||||
|
schedulerManager.pauseJob(job.getHandlerName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateJobExists(Long id) {
|
@Override
|
||||||
if (jobMapper.selectById(id) == null) {
|
public void triggerJob(Long id) throws SchedulerException {
|
||||||
throw ServiceExceptionUtil.exception(JOB_NOT_EXISTS);
|
// 校验存在
|
||||||
|
InfJobDO job = this.validateJobExists(id);
|
||||||
|
|
||||||
|
// 触发 Quartz 中的 Job
|
||||||
|
schedulerManager.triggerJob(job.getId(), job.getHandlerName(), job.getHandlerParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void deleteJob(Long id) throws SchedulerException {
|
||||||
|
// 校验存在
|
||||||
|
InfJobDO job = this.validateJobExists(id);
|
||||||
|
// 更新
|
||||||
|
jobMapper.deleteById(id);
|
||||||
|
|
||||||
|
// 删除 Job 到 Quartz 中
|
||||||
|
schedulerManager.deleteJob(job.getHandlerName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InfJobDO validateJobExists(Long id) {
|
||||||
|
InfJobDO job = jobMapper.selectById(id);
|
||||||
|
if (job == null) {
|
||||||
|
throw exception(JOB_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateCronExpression(String cronExpression) {
|
||||||
|
if (CronUtils.isValid(cronExpression)) {
|
||||||
|
throw exception(JOB_CRON_EXPRESSION_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,4 +163,10 @@ public class InfJobServiceImpl implements InfJobService {
|
||||||
return jobMapper.selectList(exportReqVO);
|
return jobMapper.selectList(exportReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void fillJobMonitorTimeoutEmpty(InfJobDO job) {
|
||||||
|
if (job.getMonitorTimeout() == null) {
|
||||||
|
job.setMonitorTimeout(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ import java.util.stream.Collectors;
|
||||||
*/
|
*/
|
||||||
public class CollectionUtils {
|
public class CollectionUtils {
|
||||||
|
|
||||||
|
public static boolean containsAny(Object source, Object... targets) {
|
||||||
|
return Arrays.asList(targets).contains(source);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isAnyEmpty(Collection<?>... collections) {
|
public static boolean isAnyEmpty(Collection<?>... collections) {
|
||||||
return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
|
return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class ${table.className}Controller {
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@ApiOperation("获得${table.classComment}")
|
@ApiOperation("获得${table.classComment}")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = ${primaryColumn.javaType}.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = ${primaryColumn.javaType}.class)
|
||||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||||
public CommonResult<${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
|
public CommonResult<${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
|
||||||
${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
|
${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
|
||||||
|
@ -72,7 +72,7 @@ public class ${table.className}Controller {
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperation("获得${table.classComment}列表")
|
@ApiOperation("获得${table.classComment}列表")
|
||||||
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class)
|
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
|
||||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||||
public CommonResult<List<${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
|
public CommonResult<List<${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
|
||||||
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
|
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
|
||||||
|
|
Loading…
Reference in New Issue