可以去quartz官网下载对应版本的包 解压后再对应的dbTables目录下有各种数据库的建表语句
实体:
/** * @author zjq * @date * <p>description:实体</p> */ @NoArgsConstructor @AllArgsConstructor @Builder @Data public class JobAndTrigger { /** * 定时任务名称 */ private String jobName; /** * 定时任务组 */ private String jobGroup; /** * 定时任务全类名 */ private String jobClassName; /** * 触发器名称 */ private String triggerName; /** * 触发器组 */ private String triggerGroup; /** * 重复间隔 */ private BigInteger repeatInterval; /** * 触发次数 */ private BigInteger timesTriggered; /** * cron 表达式 */ private String cronExpression; /** * 时区 */ private String timeZoneId; /** * 定时任务状态 */ private String triggerState; }job工厂:
@Component public class JobFactory extends AdaptableJobFactory { @Autowired private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { //调用父类的方法 Object jobInstance = super.createJobInstance(bundle); //进行注入 capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }调度器配置: 如果不配置这个启动时候会报错,无法注入org.quartz.Scheduler
@Configuration public class SchedulerConfig implements ApplicationListener<ContextRefreshedEvent> { @Autowired private JobFactory jobFactory; @Autowired @Qualifier("dataSource") private DataSource primaryDataSource; @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("任务已经启动..."+event.getSource()); } @Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException { //获取配置属性 PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); //在quartz.properties中的属性被读取并注入后再初始化对象 propertiesFactoryBean.afterPropertiesSet(); //创建SchedulerFactoryBean SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setQuartzProperties(propertiesFactoryBean.getObject()); //使用数据源,自定义数据源 factory.setDataSource(this.primaryDataSource); factory.setJobFactory(jobFactory); factory.setWaitForJobsToCompleteOnShutdown(true);//这样当spring关闭时,会等待所有已经启动的quartz job结束后spring才能完全shutdown。 factory.setOverwriteExistingJobs(false); factory.setStartupDelay(1); return factory; } /* * 通过SchedulerFactoryBean获取Scheduler的实例 */ @Bean(name="scheduler") public Scheduler scheduler() throws IOException { return schedulerFactoryBean().getScheduler(); } @Bean public QuartzInitializerListener executorListener() { return new QuartzInitializerListener(); }调度器控制类
@Controller @Slf4j public class JobController { private final JobService jobService; @Autowired public JobController(JobService jobService) { this.jobService = jobService; } @GetMapping("/job") public String applicationMain() { return "/velocity/templates/job/list"; } /** * 保存定时任务 */ @PostMapping(value = "/job/add") @ResponseBody public ResultModel<String> addJob(@RequestBody JobDTO form) { try { jobService.addJob(form); } catch (Exception e) { return new ResultModel<>(false, LoggerUtil.convertThrowableToString(e)); } return new ResultModel<String>(true, "新增成功"); } /** * 删除定时任务 */ @DeleteMapping(value = "/job/delete") @ResponseBody public ResultModel<String> deleteJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultModel<>(false,"参数不能为空"); } try{ jobService.deleteJob(form); } catch (Exception e) { return new ResultModel<>(false, LoggerUtil.convertThrowableToString(e)); } return new ResultModel<>(true, "删除成功"); } /** * 暂停定时任务 */ @PutMapping(value = "/job/pause",params = "pause") @ResponseBody public ResultModel<String> pauseJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultModel<>(false,"参数不能为空"); } try{ jobService.pauseJob(form); } catch (Exception e) { return new ResultModel<>(false, LoggerUtil.convertThrowableToString(e)); } return new ResultModel<>(true, "暂停成功"); } /** * 恢复定时任务 */ @PutMapping(value = "/job/resume",params = "resume") @ResponseBody public ResultModel<String> resumeJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultModel<>(false,"参数不能为空"); } try{ jobService.resumeJob(form); } catch (Exception e) { return new ResultModel<>(false, LoggerUtil.convertThrowableToString(e)); } return new ResultModel<>(true, "恢复成功"); } /** * 修改定时任务,定时时间 */ @PutMapping(value = "/job/cron",params = "cron") @ResponseBody public ResultModel<String> cronJob(@Valid JobForm form) { try { jobService.cronJob(form); } catch (Exception e) { return new ResultModel<>(false, LoggerUtil.convertThrowableToString(e)); } return new ResultModel<>(true, "修改成功"); } @PostMapping(value = "/job/query") @ResponseBody public ResultModel<Page> jobList(@RequestBody JobDTO jobDTO) { Integer currentPage=1; Integer pageSize=10; if (ObjectUtil.isNull(currentPage)) { currentPage = 1; } if (ObjectUtil.isNull(pageSize)) { pageSize = 10; } //IPage<JobAndTrigger> all = null; Page<JobAndTrigger> all = null; try{ all = jobService.list(currentPage, pageSize); } catch (Exception e) { return new ResultModel<>(false, null); } return new ResultModel<>(true, all); } @RequestMapping(value = "/job/editPrepare", method = RequestMethod.POST) public String editPrepare(Model model, @RequestBody JobDTO jobDTO) { model.addAttribute("requirementDTO", jobDTO); return "/velocity/templates/job/saveOrUpdate"; } ``` 调度器接口和实现类: ```java /** * @author zjq * @date 2019 * <p>description:定時任务接口</p> */ public interface JobService { /** * 添加并启动定时任务 * * @param form 表单参数 {@link JobForm} * @throws Exception 异常 */ void addJob(JobDTO form) throws Exception; /** * 删除定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ void deleteJob(JobForm form) throws SchedulerException; /** * 暂停定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ void pauseJob(JobForm form) throws SchedulerException; /** * 恢复定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ void resumeJob(JobForm form) throws SchedulerException; /** * 重新配置定时任务 * * @param form 表单参数 {@link JobForm} * @throws Exception 异常 */ void cronJob(JobForm form) throws Exception; /** * 查询定时任务列表 * * @param currentPage 当前页 * @param pageSize 每页条数 * @return 定时任务列表 */ Page<JobAndTrigger> list(Integer currentPage, Integer pageSize); } @Service @Slf4j public class JobServiceImpl implements JobService { private final Scheduler scheduler; private final JobMapper jobMapper; @Autowired public JobServiceImpl(Scheduler scheduler, JobMapper jobMapper) { this.scheduler = scheduler; this.jobMapper = jobMapper; } /** * 添加并启动定时任务 * * @param form 表单参数 {@link JobForm} * @return {@link JobDetail} * @throws Exception 异常 */ @Override public void addJob(JobDTO form) throws Exception { // 启动调度器 scheduler.start(); // 构建Job信息 JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobClassName(), form.getJobGroup()).build(); // Cron表达式调度构建器(即任务执行的时间) CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getCronExpression()); //根据Cron表达式构建一个Trigger CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobClassName(), form.getJobGroup()).withSchedule(cron).build(); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { log.error("【定时任务】创建失败!", e); throw new Exception("【定时任务】创建失败!"); } } /** * 删除定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ @Override public void deleteJob(JobForm form) throws SchedulerException { scheduler.pauseTrigger(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName())); scheduler.unscheduleJob(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName())); scheduler.deleteJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName())); } /** * 暂停定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ @Override public void pauseJob(JobForm form) throws SchedulerException { scheduler.pauseJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName())); } /** * 恢复定时任务 * * @param form 表单参数 {@link JobForm} * @throws SchedulerException 异常 */ @Override public void resumeJob(JobForm form) throws SchedulerException { scheduler.resumeJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName())); } /** * 重新配置定时任务 * * @param form 表单参数 {@link JobForm} * @throws Exception 异常 */ @Override public void cronJob(JobForm form) throws Exception { try { TriggerKey triggerKey = TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()); // 表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(form.getCronExpression()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 根据Cron表达式构建一个Trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); // 按新的trigger重新设置job执行 scheduler.rescheduleJob(triggerKey, trigger); } catch (SchedulerException e) { log.error("【定时任务】更新失败!", e); throw new Exception("【定时任务】创建失败!"); } } /** * 查询定时任务列表 * * @param currentPage 当前页 * @param pageSize 每页条数 * @return 定时任务列表 */ // @Override // public IPage<JobAndTrigger> list(Integer currentPage, Integer pageSize) { // // QueryWrapper queryWrapper = new QueryWrapper(); // Page<JobAndTrigger> pojo = new Page<>(currentPage, pageSize); // IPage<JobAndTrigger> page = this.page(pojo, queryWrapper); // List<JobAndTrigger> list = JSON.parseArray(JSON.toJSONString(page.getRecords()), JobAndTrigger.class); // page.setRecords(list); // return page; // } @Override public Page<JobAndTrigger> list(Integer currentPage, Integer pageSize) { Page<JobAndTrigger> pojo = new Page<>(currentPage,pageSize); List<JobAndTrigger> list = jobMapper.list(pojo); pojo.setRecords(list); return pojo; } } ``` 前端代码: <div style="height:100%; overflow:scroll"> <form class="layui-form" action=""> <!--$csrfToken.hiddenField--> <!--场景查询条件--> <div class="layui-form-item"> <label class="layui-form-label">任务名称</label> <div class="layui-input-inline"> <input type="text" name="jobName" class="layui-input" id="jobName"/> </div> <label class="layui-form-label" style="width: 150px">任务状态:</label> <div class="layui-input-inline" style="width: 170px"> <select name="jobType" id="jobType" style="width: max-content"> <option value="" selected>请选择任务状态</option> <option value="RUNNING">运行中</option> <option value="PAUSED">暂停</option> </select> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="job_query">查询</button> <button type="reset" class="layui-btn layui-btn-primary">重置</button> </div> </div> </form> <hr/> <table class="layui-table" id="job_list" lay-filter="job_list"> </table> </div> <!-- 表头批量操作工具 --> <script type="text/html" id="headToolbar"> <div class="layui-btn-container"> <button class="layui-btn layui-btn-sm" lay-event="add">新增</button> </div> </script> <!--表格中便捷toolbar--> <script type="text/html" id="barTool"> <a class="layui-btn layui-btn-xs" lay-size="lg" lay-event="job_edit" style="width: 50px">编辑</a> #*<a class="layui-btn layui-btn-xs" lay-size="lg" lay-event="job_remove">删除</a>*# </script> <script type="text/html" id="jobTypeBar"> <div> {{# if(d.jobType === "MAIN"){ }} 主干回归用例 {{# }else if(d.jobType === "PROJECT"){ }} 项目测试用例 {{# }else{ }} 自定义用例 {{# } }} </div> </script> <script src="/js/3rdParty/jquery-3.2.1.min.js"></script> <script src="/js/job/job_list.js"></script> <div> <form class="layui-form"> <!--$csrfToken.hiddenField--> <br/> <br/> <!--projectId--> <input type="hidden" name="id" value="$!{jobDTO.id}"> ## <input type="hidden" id="tempDto" name="dto" value="$!{jobDTO}"> <br/> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">任务名称:</label> <div class="layui-input-inline" style="width: 70%"> <input type="text" name="jobName" id="jobName" value="$!{jobDTO.jobName}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">任务组:</label> <div class="layui-input-inline" style="width: 70%"> <input type="text" name="jobGroup" id="jobGroup" value="$!{jobDTO.jobGroup}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">任务全类名:</label> <div class="layui-input-inline" style="width: 70%"> <input type="text" name="jobClassName" id="jobClassName" value="$!{jobDTO.jobClassName}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">cron表达式:</label> <div class="layui-input-inline" style="width: 70%"> <input type="text" name="cronExpression" id="cronExpression" value="$!{jobDTO.cronExpression}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">提醒信息:</label> <div class="layui-input-inline" style="width: 70%"> <input type="areatext" name="notice" id="notice" value="$!{jobDTO.notice}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <div class="layui-form-item" style="width: 100%"> <label class="layui-form-label" style="width: 20%">@人员数组:</label> <div class="layui-input-inline" style="width: 70%"> <input type="areatext" name="atPersons" id="atPersons" value="$!{jobDTO.atPersons}" required lay-verify="required" class="layui-input projId"></input> </div> </div> <br/> <!--*************此处提交部分******************--> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn layui-btn-sm" lay-submit lay-filter="onSubmit">保存</button> <button type="reset" class="layui-btn layui-btn-primary layui-btn-sm">重置</button> </div> </div> </form> </div>