正文
Springboot + Vue,定时任务调度的全套实现方案。
这里用了quartz这个框架,实现分布式调度任务很不错,关于quarz的使用方式改天补一篇。相当简单。
1、表结构:
sys_job | |||||
---|---|---|---|---|---|
列名 | 数据类型 | 长度 | 是否可空 | 是否主键 | 说明 |
job_id | bigint | 否 | 是 | 任务ID | |
job_name | varchar | 64 | 否 | 是 | 任务名称 |
job_group | varchar | 64 | 否 | 是 | 任务组名 |
invoke_target | varchar | 500 | 否 | 否 | 调用目标字符串 |
cron_expression | varchar | 255 | 是 | 否 | cron执行表达式 |
misfire_policy | varchar | 20 | 是 | 否 | 计划执行错误策略(1立即执行 2执行一次 3放弃执行) |
concurrent | char | 1 | 是 | 否 | 是否并发执行(0允许 1禁止) |
status | char | 1 | 是 | 否 | 状态(0正常 1暂停) |
create_by | varchar | 64 | 是 | 否 | 创建者 |
create_time | datetime | 是 | 否 | 创建时间 | |
update_by | varchar | 64 | 是 | 否 | 更新者 |
update_time | datetime | 是 | 否 | 更新时间 | |
remark | varchar | 500 | 是 | 否 | 备注信息 |
2、接口:
@RestController @RequestMapping("/job") public class SysJobController extends BaseController { @Autowired private ISysJobService jobService; /** * 查询定时任务列表 */ @GetMapping("/list") public TableDataInfo list(SysJob sysJob) { startPage(); Listlist = jobService.selectJobList(sysJob); return getDataTable(list); } /** * 导出定时任务列表 */ @PostMapping("/export") public void export(HttpServletResponse response, SysJob sysJob) { List list = jobService.selectJobList(sysJob); ExcelUtil util = new ExcelUtil (SysJob.class); util.exportExcel(response, list, "定时任务"); } /** * 获取定时任务详细信息 */ @GetMapping(value = "/{jobId}") public AjaxResult getInfo(@PathVariable("jobId") Long jobId) { return success(jobService.selectJobById(jobId)); } /** * 新增定时任务 */ @PostMapping public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException { if (!CronUtils.isValid(job.getCronExpression())) { return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确"); } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) { return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) { return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) { return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) { return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规"); } else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) { return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); } job.setCreateBy(getUsername()); return toAjax(jobService.insertJob(job)); } /** * 修改定时任务 */ @PutMapping public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException { if (!CronUtils.isValid(job.getCronExpression())) { return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确"); } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) { return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) { return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) { return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) { return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规"); } else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) { return error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); } job.setUpdateBy(getUsername()); return toAjax(jobService.updateJob(job)); } /** * 定时任务状态修改 */ @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)); } /** * 定时任务立即执行一次 */ @PutMapping("/run") public AjaxResult run(@RequestBody SysJob job) throws SchedulerException { boolean result = jobService.run(job); return result ? success() : error("任务不存在或已过期!"); } /** * 删除定时任务 */ @DeleteMapping("/{jobIds}") public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException { jobService.deleteJobByIds(jobIds); return success(); } 复制代码
3、业务层:
public interface ISysJobService { /** * 获取quartz调度器的计划任务 * * @param job 调度信息 * @return 调度任务集合 */ public ListselectJobList(SysJob job); /** * 通过调度任务ID查询调度信息 * * @param jobId 调度任务ID * @return 调度任务对象信息 */ public SysJob selectJobById(Long jobId); /** * 暂停任务 * * @param job 调度信息 * @return 结果 */ public int pauseJob(SysJob job) throws SchedulerException; /** * 恢复任务 * * @param job 调度信息 * @return 结果 */ public int resumeJob(SysJob job) throws SchedulerException; /** * 删除任务后,所对应的trigger也将被删除 * * @param job 调度信息 * @return 结果 */ public int deleteJob(SysJob job) throws SchedulerException; /** * 批量删除调度信息 * * @param jobIds 需要删除的任务ID * @return 结果 */ public void deleteJobByIds(Long[] jobIds) throws SchedulerException; /** * 任务调度状态修改 * * @param job 调度信息 * @return 结果 */ public int changeStatus(SysJob job) throws SchedulerException; /** * 立即运行任务 * * @param job 调度信息 * @return 结果 */ public boolean run(SysJob job) throws SchedulerException; /** * 新增任务 * * @param job 调度信息 * @return 结果 */ public int insertJob(SysJob job) throws SchedulerException, TaskException; /** * 更新任务 * * @param job 调度信息 * @return 结果 */ public int updateJob(SysJob job) throws SchedulerException, TaskException; /** * 校验cron表达式是否有效 * * @param cronExpression 表达式 * @return 结果 */ public boolean checkCronExpressionIsValid(String cronExpression); } 复制代码
@Service public class SysJobServiceImpl implements ISysJobService { @Autowired private Scheduler scheduler; @Autowired private SysJobMapper jobMapper; /** * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) */ @PostConstruct public void init() throws SchedulerException, TaskException { scheduler.clear(); ListjobList = jobMapper.selectJobAll(); for (SysJob job : jobList) { ScheduleUtils.createScheduleJob(scheduler, job); } } /** * 获取quartz调度器的计划任务列表 * * @param job 调度信息 * @return */ @Override public List 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(rollbackFor = Exception.class) 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(rollbackFor = Exception.class) 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(rollbackFor = Exception.class) 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(rollbackFor = Exception.class) public void deleteJobByIds(Long[] jobIds) throws SchedulerException { for (Long jobId : jobIds) { SysJob job = jobMapper.selectJobById(jobId); deleteJob(job); } } /** * 任务调度状态修改 * * @param job 调度信息 */ @Override @Transactional(rollbackFor = Exception.class) 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(rollbackFor = Exception.class) public boolean run(SysJob job) throws SchedulerException { boolean result = false; Long jobId = job.getJobId(); String jobGroup = job.getJobGroup(); SysJob properties = selectJobById(job.getJobId()); // 参数 JobDataMap dataMap = new JobDataMap(); dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); if (scheduler.checkExists(jobKey)) { result = true; scheduler.triggerJob(jobKey, dataMap); } return result; } /** * 新增任务 * * @param job 调度信息 调度信息 */ @Override @Transactional(rollbackFor = Exception.class) 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(rollbackFor = Exception.class) 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); } } 复制代码
4、Mapper
public interface SysJobMapper { /** * 查询调度任务日志集合 * * @param job 调度信息 * @return 操作日志集合 */ public ListselectJobList(SysJob job); /** * 查询所有调度任务 * * @return 调度任务列表 */ public List selectJobAll(); /** * 通过调度ID查询调度任务信息 * * @param jobId 调度ID * @return 角色对象信息 */ public SysJob selectJobById(Long jobId); /** * 通过调度ID删除调度任务信息 * * @param jobId 调度ID * @return 结果 */ public int deleteJobById(Long jobId); /** * 批量删除调度任务信息 * * @param ids 需要删除的数据ID * @return 结果 */ public int deleteJobByIds(Long[] ids); /** * 修改调度任务信息 * * @param job 调度任务信息 * @return 结果 */ public int updateJob(SysJob job); /** * 新增调度任务信息 * * @param job 调度任务信息 * @return 结果 */ public int insertJob(SysJob job); } 复制代码
复制代码select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark from sys_job delete from sys_job where job_id = #{jobId} delete from sys_job where job_id in #{jobId} update sys_job where job_id = #{jobId} job_name = #{jobName}, job_group = #{jobGroup}, invoke_target = #{invokeTarget}, cron_expression = #{cronExpression}, misfire_policy = #{misfirePolicy}, concurrent = #{concurrent}, status = #{status}, remark = #{remark}, update_by = #{updateBy}, update_time = sysdate()insert into sys_job( job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, remark, create_by, create_time )values(#{jobId}, #{jobName}, #{jobGroup}, #{invokeTarget}, #{cronExpression}, #{misfirePolicy}, #{concurrent}, #{status}, #{remark}, #{createBy}, sysdate() )
5、前端(Vue):
import request from '@/utils/request' // 查询定时任务调度列表 export function listJob(query) { return request({ url: '/monitor/job/list', method: 'get', params: query }) } // 查询定时任务调度详细 export function getJob(jobId) { return request({ url: '/monitor/job/' + jobId, method: 'get' }) } // 新增定时任务调度 export function addJob(data) { return request({ url: '/monitor/job', method: 'post', data: data }) } // 修改定时任务调度 export function updateJob(data) { return request({ url: '/monitor/job', method: 'put', data: data }) } // 删除定时任务调度 export function delJob(jobId) { return request({ url: '/monitor/job/' + jobId, method: 'delete' }) } // 任务状态修改 export function changeJobStatus(jobId, status) { const data = { jobId, status } return request({ url: '/monitor/job/changeStatus', method: 'put', data: data }) } // 定时任务立即执行一次 export function runJob(jobId, jobGroup) { const data = { jobId, jobGroup } return request({ url: '/monitor/job/run', method: 'put', data: data }) } 复制代码
import request from '@/utils/request' // 查询调度日志列表 export function listJobLog(query) { return request({ url: '/monitor/jobLog/list', method: 'get', params: query }) } // 删除调度日志 export function delJobLog(jobLogId) { return request({ url: '/monitor/jobLog/' + jobLogId, method: 'delete' }) } // 清空调度日志 export function cleanJobLog() { return request({ url: '/monitor/jobLog/clean', method: 'delete' }) } 复制代码
复制代码 搜索 重置 新增 修改 删除 导出 日志 修改 删除 handleCommand(command, scope.row)" v-hasPermi="['monitor:job:changeStatus', 'monitor:job:query']"> 更多 执行一次 任务详细 调度日志 调用方法 Bean调用示例:ryTask.ryParams('ry')
Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')
参数说明:支持字符串,布尔类型,长整型,浮点型,整型生成表达式 立即执行 执行一次 放弃执行 允许 禁止 {{dict.label}} {{ form.jobId }} {{ form.jobName }} {{ jobGroupFormat(form) }} {{ form.createTime }} {{ form.cronExpression }} {{ parseTime(form.nextValidTime) }} {{ form.invokeTarget }} 正常失败 允许禁止 默认策略立即执行执行一次放弃执行
搜索 重置 删除 清空 导出 关闭 {{ parseTime(scope.row.createTime) }} 详细 {{ form.jobLogId }} {{ form.jobName }} {{ form.jobGroup }} {{ form.createTime }} {{ form.invokeTarget }} {{ form.jobMessage }} 正常失败{{ form.exceptionInfo }}
以上就是Springboot Vue可配置调度任务实现示例详解的详细内容,更多关于Springboot Vue配置调度任务的资料请关注脚本之家其它相关文章!