当前位置:网站首页>Spingboot integrates the quartz framework to realize dynamic scheduled tasks (support real-time addition, deletion, modification and query tasks)
Spingboot integrates the quartz framework to realize dynamic scheduled tasks (support real-time addition, deletion, modification and query tasks)
2022-07-29 07:19:00 【@Primes~】
SpingBoot Integrate Quartz The framework implements dynamic scheduled tasks ( Support real-time addition, deletion, modification and query tasks )
- 1. Preface
- 2. About Quartz Introduction and recommendation
- 3. For reference code address, please enter
- 4. Look at the effect
- 5. preparation
- 6. Core code ( Directly stick down the code )
- 7. Implement a business scenario
- 8. The attached code
1. Preface
The last article on dynamic timed tasks
SpringBoot Dynamic configuration processing of dynamic timing tasks ( Dynamically read the database configuration in real time , Support dynamic modification and new tasks without restarting the service ).This method is simple , But there will be many disadvantages , You can search online , Maybe I haven't figured it out yet , So I don't think it's easy to use , So I recommend you to use today's introduction Quartz frame , Of course, choose according to your needs
2. About Quartz Introduction and recommendation
Recommend a very good article , You can see that , This article will not introduce , I'll go directly to the case later , Want to know more , Take a look at the following article , It's still very friendly to explain the children's shoes that you just touched .
Timing task framework Quartz-( One )Quartz Introduction and Demo build .
3. For reference code address, please enter
- Shared by friends clone The code of the following address , I found that there was an introduction Quartz, Originally, I always wanted to make a question about Quartz Of demo, I haven't done it , After reading it, I think it's necessary to make a demo Show me , I recommend you clone Boss upload to gitHub The code on , If you don't clone Look directly at me demo It's OK , What I have done below is to make changes , The initialization table is also less
https://github.com/xkcoding/spring-boot-demo.
4. Look at the effect
- New task

- Inquire about 、 modify state 、 Delete etc.

5. preparation
5.1 database
- ① Initialize the following tables :qrtz, Just create a table , No data , Post after the statement of creating table , Originally 11 A watch , I use these here , So if you build all the tables , You can refer to the above github Upper

- After adding tasks to the page, the data of these tables will be automatically filled , Of course, you can also directly insert, Just a little trouble , First, take a brief look at the data structure of these tables in the screenshot


dog_play_planThis table is created according to the business logic , Later on
5.2 Java Back end configuration, etc
5.2.1 pom file
- as follows :

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
5.2.2 yml The configuration file
- as follows :

spring: quartz: # See org.springframework.boot.autoconfigure.quartz.QuartzProperties job-store-type: jdbc wait-for-jobs-to-complete-on-shutdown: true scheduler-name: SpringBootDemoScheduler properties: org.quartz.threadPool.threadCount: 5 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true org.quartz.jobStore.misfireThreshold: 5000 org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # In the first step of the scheduling process , That is, pull the to be triggered triggers when , It's locked , That is, there will not be multiple threads pulling to the same trigger The situation of , This avoids the risk of repeated scheduling . Reference resources :https://segmentfault.com/a/1190000015492260 org.quartz.jobStore.acquireTriggersWithinLock: true # org.quartz.jobStore.tablePrefix: sys_
6. Core code ( Directly stick down the code )
6.1 vo、mapper And mapper.xml
- Pictured :



6.2 controller、service
- First cut a new , Other code posted below



6.3 JobUtil.java
- Pictured :

6.4 BaseJob、 timing job(HelloJob For example )
- Pictured :


6.5 job.html
- Pictured :

6.6 Test to see the effect
- ① Start the service , New task , View the new tasks




- ② Disable task


If it's enabled again , Click restore , Fool operation is not introduced , Mainly code implementation
7. Implement a business scenario
7.1 dog_play_plan—— schedule
- Just talk about the watch , Entities and mapper and xml Omitted


7.2 DogPlayPlanJob.java
- as follows :

Of course, you can also deal with business directly , Don't get the schedule , Look at yourself , Why make a schedule , For example, send text messages ,SendMessageJobThere is one , But there are 2 Send it every minute, some 5 Every minute , So you can form the same groupsendMessageBut different task names2 Minutes at a timeand5 Minutes at a time, But what business data do you need to deal with 2 Minutes at a time , What to 5 Minutes at a time , Of course, my schedule may not be more reasonable , So we need to optimize according to our own needs
7.3 test
- Start the service , Add business , Test the following :


7.3 You can optimize later
1. Control the data of adding tasks
- New tasks cannot be added randomly , Therefore, the business name 、 Full class name maintenance dictionary or enumeration, or directly maintain the form data into a table , Check the data to reverse display , Ensure data correctness , Especially the full class name or cron expression
2. dog_play_plan surface
- This table is optimized according to your needs , Here is just a simple analogy
3. Timed task management should be made into permission control
- This function is relatively important , You can control the page , But we should make it into permission control , You can't add, delete, modify or check at will
- Okay , In short, so much , Just watch the optimization by yourself
7.4 Right up there 7.3 Proposed to carry out a simple optimization
1. Maintain with enumeration jobGroupName and jobName
- To avoid data scribbling when adding new tasks , So maintain

2. newly added sys_job_manager surface —— Used to manage the addition of scheduled tasks
- The table structure is as follows :


- purpose :
This table can be maintained by developers in the background , When adding tasks to the page , Take the data maintained in this table , If there is no maintenance, it is not allowed to add tasks randomly
3. Control the query of adding tasks sql
- Query all tasks that can be added :

- Check whether the added task is maintained

4. controller Revised as follows
- as follows

5. When added , Pay attention to the data
- as follows :

6. Don't forget dog_play_plan
- This watch depends on the situation , No corresponding plan can be maintained , But first maintain the above tasks , Add this plan

This table , Optimize according to your own needs , It probably means this
8. The attached code
8.1 Database tables
- In the following order :
CREATE TABLE `qrtz_cron_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `CRON_EXPRESSION` varchar(200) NOT NULL, `TIME_ZONE_ID` varchar(80) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `qrtz_fired_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(95) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(20) NOT NULL, `SCHED_TIME` bigint(20) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` bit(1) DEFAULT NULL, `REQUESTS_RECOVERY` bit(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `qrtz_job_details` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` bit(1) NOT NULL, `IS_NONCONCURRENT` bit(1) NOT NULL, `IS_UPDATE_DATA` bit(1) NOT NULL, `REQUESTS_RECOVERY` bit(1) NOT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `qrtz_locks` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `qrtz_paused_trigger_grps` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=' No startup error '; CREATE TABLE `qrtz_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(20) DEFAULT NULL, `PREV_FIRE_TIME` bigint(20) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(20) NOT NULL, `END_TIME` bigint(20) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(6) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `qrtz_simple_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(20) NOT NULL, `REPEAT_INTERVAL` bigint(20) NOT NULL, `TIMES_TRIGGERED` bigint(20) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=' Use this when modifying scheduled tasks ';
8.2 Java Core code
1. vo、mapper And mapper.xml etc.
- ① JobForm.java
package com.liu.susu.task.quartz.vobo.form; import lombok.Data; import lombok.experimental.Accessors; import javax.validation.constraints.NotBlank; @Data @Accessors(chain = true) public class JobForm { /** * Time task name */ @NotBlank(message = " The name of the task ") private String jobName; /** * Task force name */ @NotBlank(message = " Task group name cannot be empty ") private String jobGroupName; /** * Full class name of scheduled task */ @NotBlank(message = " Full class name of scheduled task ") private String jobClassName; /** * Timing task cron expression */ @NotBlank(message = "cron Expression cannot be empty ") private String cronExpression; } - ② JobAndTriggerVo.java
package com.liu.susu.task.quartz.vobo.vo; import lombok.Data; import java.math.BigInteger; @Data public class JobAndTriggerVo { /** * Timing task name */ private String jobName; /** * Timed task force */ private String jobGroup; /** * Full class name of scheduled task */ private String jobClassName; /** * Trigger Name */ private String triggerName; /** * Trigger group */ private String triggerGroup; /** * Repeat interval */ private BigInteger repeatInterval; /** * Number of triggers */ private BigInteger timesTriggered; /** * cron expression */ private String cronExpression; /** * The time zone */ private String timeZoneId; /** * Scheduled task status */ private String triggerState; } - ③ JobMapper.java
package com.liu.susu.mapper.task; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; @Mapper @Repository public interface JobMapper { /** * Query the list of scheduled jobs and triggers */ List<JobAndTriggerVo> list(); } - ④ JobMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.liu.susu.mapper.task.JobMapper"> <select id="list" resultType="com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo"> SELECT job_details.`JOB_NAME`, job_details.`JOB_GROUP`, job_details.`JOB_CLASS_NAME`, cron_triggers.`CRON_EXPRESSION`, cron_triggers.`TIME_ZONE_ID`, qrtz_triggers.`TRIGGER_NAME`, qrtz_triggers.`TRIGGER_GROUP`, qrtz_triggers.`TRIGGER_STATE` FROM `QRTZ_JOB_DETAILS` job_details LEFT JOIN `QRTZ_CRON_TRIGGERS` cron_triggers ON job_details.`JOB_NAME` = cron_triggers.`TRIGGER_NAME` AND job_details.`JOB_GROUP` = cron_triggers.`TRIGGER_GROUP` LEFT JOIN `QRTZ_TRIGGERS` qrtz_triggers ON qrtz_triggers.`TRIGGER_NAME` = job_details.`JOB_NAME` AND qrtz_triggers.`TRIGGER_GROUP` = job_details.`JOB_GROUP` </select> </mapper>
2. controller、service
- ① JobController.java
package com.liu.susu.controller.task; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.github.pagehelper.PageInfo; import com.liu.susu.common.ResultData; import com.liu.susu.common.ReturnCode; import com.liu.susu.service.task.JobService; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import com.liu.susu.task.quartz.vobo.form.JobForm; import lombok.extern.slf4j.Slf4j; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @RestController @RequestMapping("/job") @Slf4j public class JobController { private final JobService jobService; @Autowired public JobController(JobService jobService) { this.jobService = jobService; } /** * Save scheduled tasks */ @PostMapping public ResultData addJob(@Valid JobForm form) { try { jobService.addJob(form); return new ResultData(ReturnCode.INSERT_SUCCESS); } catch (Exception e) { return new ResultData(ReturnCode.FAIL_999999); } } /** * Pause scheduled tasks */ @PutMapping(params = "pause") public ResultData pauseJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultData(ReturnCode.FAIL_NO_PARAM, " The parameter cannot be null !"); } jobService.pauseJob(form); return new ResultData(ReturnCode.SUCCESS_000000, " Pause succeeded !"); } /** * Resume scheduled tasks */ @PutMapping(params = "resume") public ResultData resumeJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultData(ReturnCode.FAIL_NO_PARAM, " The parameter cannot be null !"); } jobService.resumeJob(form); return new ResultData(ReturnCode.SUCCESS_000000, " Recovery successful !"); } /** * Modify scheduled tasks , Timing time */ @PutMapping(params = "cron") public ResultData cronJob(@Valid JobForm form) { try { jobService.cronJob(form); return new ResultData(ReturnCode.UPDATE_SUCCESS, " Modification successful !"); } catch (Exception e) { return new ResultData(ReturnCode.FAIL_999999); } } /** * Delete scheduled tasks */ @DeleteMapping public ResultData deleteJob(JobForm form) throws SchedulerException { if (StrUtil.hasBlank(form.getJobGroupName(), form.getJobClassName())) { return new ResultData(ReturnCode.FAIL_NO_PARAM, " The parameter cannot be null !"); } jobService.deleteJob(form); return new ResultData(ReturnCode.DELETE_SUCCESS, " Delete successful !"); } /** * Query the scheduled task list * @param currentPage * @param pageSize * @return */ @RequestMapping public ResultData jobList(Integer currentPage, Integer pageSize) { if (ObjectUtil.isNull(currentPage)) { currentPage = 1; } if (ObjectUtil.isNull(pageSize)) { pageSize = 10; } PageInfo<JobAndTriggerVo> all = jobService.list(currentPage, pageSize); return new ResultData(ReturnCode.SELECT_SUCCESS, all); } } - ② JobService.java
package com.liu.susu.service.task; import com.github.pagehelper.PageInfo; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import com.liu.susu.task.quartz.vobo.form.JobForm; import org.quartz.SchedulerException; public interface JobService { /** * Add and start scheduled tasks */ void addJob(JobForm form) throws Exception; /** * Delete scheduled tasks */ void deleteJob(JobForm form) throws SchedulerException; /** * Pause scheduled tasks */ void pauseJob(JobForm form) throws SchedulerException; /** * Resume scheduled tasks */ void resumeJob(JobForm form) throws SchedulerException; /** * Reconfigure scheduled tasks */ void cronJob(JobForm form) throws Exception; /** * Query the scheduled task list */ PageInfo<JobAndTriggerVo> list(Integer currentPage, Integer pageSize); } - ③ JobServiceImpl.java
package com.liu.susu.service.task.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.liu.susu.mapper.task.JobMapper; import com.liu.susu.service.task.JobService; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import com.liu.susu.task.quartz.vobo.form.JobForm; import com.liu.susu.utils.JobUtil; import lombok.extern.slf4j.Slf4j; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @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; } /** * Add and start scheduled tasks */ @Override public void addJob(JobForm form) throws Exception { // Start the scheduler scheduler.start(); // structure Job Information // JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobClassName(), form.getJobGroupName()).build(); JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobName(), form.getJobGroupName()).build(); // Cron Expression scheduling builder ( That is, the time of task execution ) CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getCronExpression()); // according to Cron Expression builds a Trigger // CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobClassName(), form.getJobGroupName()).withSchedule(cron).build(); CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobName(), form.getJobGroupName()).withSchedule(cron).build(); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { log.error("【 Timing task 】 Create failure !", e); throw new Exception("【 Timing task 】 Create failure !"); } } /** * Delete scheduled tasks */ @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())); } /** * Pause scheduled tasks */ @Override public void pauseJob(JobForm form) throws SchedulerException { scheduler.pauseJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName())); } /** * Resume scheduled tasks */ @Override public void resumeJob(JobForm form) throws SchedulerException { scheduler.resumeJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName())); } /** * Reconfigure scheduled tasks */ @Override public void cronJob(JobForm form) throws Exception { try { TriggerKey triggerKey = TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()); // Expression scheduling builder CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(form.getCronExpression()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // according to Cron Expression builds a Trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); // Press new trigger To reset job perform scheduler.rescheduleJob(triggerKey, trigger); } catch (SchedulerException e) { log.error("【 Timing task 】 Update failed !", e); throw new Exception("【 Timing task 】 Create failure !"); } } /** * Query the scheduled task list */ @Override public PageInfo<JobAndTriggerVo> list(Integer currentPage, Integer pageSize) { PageHelper.startPage(currentPage, pageSize); List<JobAndTriggerVo> list = jobMapper.list(); return new PageInfo<>(list); } }
3. JobUtil.java
- as follows :
package com.liu.susu.utils; import com.liu.susu.task.quartz.job.base.BaseJob; /** * Timed task reflection tool class */ public class JobUtil { /** * Get the full class name Job example */ public static BaseJob getClass(String classname) throws Exception { Class<?> clazz = Class.forName(classname); return (BaseJob) clazz.newInstance(); } }
4. BaseJob、HelloJob
- ① BaseJob.java
package com.liu.susu.task.quartz.job.base; import org.quartz.*; public interface BaseJob extends Job { @Override void execute(JobExecutionContext context) throws JobExecutionException; } - ② HelloJob.java
package com.liu.susu.task.quartz.job; import com.liu.susu.task.quartz.job.base.BaseJob; import lombok.extern.slf4j.Slf4j; import org.quartz.JobExecutionContext; import org.quartz.JobKey; import java.time.LocalDateTime; @Slf4j public class HelloJob implements BaseJob { @Override public void execute(JobExecutionContext context) { JobKey key = context.getJobDetail().getKey(); if ("bb".equals(key.getName())){ log.info(" Handle bb Business of scheduled tasks …… execution time -->: {}", LocalDateTime.now()); } if ("aa".equals(key.getName())){ log.info(" Handle aa Business of scheduled tasks …… execution time -->: {}",LocalDateTime.now()); } log.info(" Handle aa、bb External scheduled tasks , execution time -->: {}",LocalDateTime.now()); } }
5. job.html
- as follows :
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>spring-boot-demo-task-quartz</title> <link href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.9/theme-chalk/index.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/vue/2.5.17/vue.min.js"></script> <script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.9/index.js"></script> <style> #top { /*background: #20A0FF;*/ padding: 5px; /*overflow: hidden*/ } </style> </head> <body> <div id="job"> <div id="top"> <el-button size="small" type="primary" plain @click="search" :loading="loading" icon="el-icon-search"> Inquire about </el-button> <el-button size="small" type="primary" plain @click="handleadd" icon="el-icon-plus"> add to </el-button> </div> <br/> <div> <el-table ref="jobTable" :data="tableData" style="width:100%" border center> <el-table-column prop="jobName" label=" The name of the task " show-overflow-tooltip align="center"></el-table-column> <el-table-column prop="jobGroup" label=" Task group " sortable align="center"></el-table-column> <el-table-column prop="jobClassName" label=" Task class name " align="center"></el-table-column> <el-table-column prop="triggerName" label=" Trigger Name " align="center"></el-table-column> <el-table-column prop="triggerGroup" label=" Trigger group " sortable align="center"></el-table-column> <el-table-column prop="cronExpression" label=" expression " align="center"></el-table-column> <el-table-column prop="timeZoneId" label=" The time zone " align="center"></el-table-column> <el-table-column prop="triggerState" label=" state " align="center" :formatter="formatState"></el-table-column> <el-table-column label=" operation " width="300" align="center"> <template scope="scope"> <el-button size="small" type="warning" @click="handlePause(scope.$index, scope.row)"> Pause </el-button> <el-button size="small" type="info" @click="handleResume(scope.$index, scope.row)"> recovery </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"> Delete </el-button> <el-button size="small" type="success" @click="handleUpdate(scope.$index, scope.row)"> modify </el-button> </template> </el-table-column> </el-table> <div align="center"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="totalCount"> </el-pagination> </div> </div> <el-dialog title=" Add tasks " :visible.sync="dialogFormVisible"> <el-form :model="form"> <el-form-item label=" The name of the task " label-width="100px" style="width:90%"> <el-input v-model="form.jobName" auto-complete="off"></el-input> </el-form-item> <el-form-item label=" Task class name " label-width="100px" style="width:90%"> <el-input v-model="form.jobClassName" auto-complete="off"></el-input> </el-form-item> <el-form-item label=" Task groups " label-width="100px" style="width:90%"> <el-input v-model="form.jobGroup" auto-complete="off"></el-input> </el-form-item> <el-form-item label=" expression " label-width="100px" style="width:90%"> <el-input v-model="form.cronExpression" auto-complete="off"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false"> take eliminate </el-button> <el-button type="primary" @click="add"> indeed set </el-button> </div> </el-dialog> <el-dialog title=" Modify task " :visible.sync="updateFormVisible"> <el-form :model="updateform"> <el-form-item label=" expression " label-width="100px" style="width:90%"> <el-input v-model="updateform.cronExpression" auto-complete="off"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="updateFormVisible = false"> take eliminate </el-button> <el-button type="primary" @click="update"> indeed set </el-button> </div> </el-dialog> </div> <footer align="center"> <p>© Quartz Timed task management </p> </footer> <script> var vue = new Vue({ el: "#job", data: { // Table current page data tableData: [], // Requested URL url: 'job', // The default data volume per page pagesize: 10, // The current page number currentPage: 1, // Page number of the query start: 1, // Default total data totalCount: 1000, // Add dialog default visibility dialogFormVisible: false, // Modify the default visibility of the dialog updateFormVisible: false, // Submitted forms form: { jobName: '', jobGroup: '', cronExpression: '' }, updateform: { jobName: '', jobGroup: '', cronExpression: '' }, loading: false }, methods: { // Format state formatState: function (row, column, cellValue, index) { if (row.triggerState === 'WAITING' || row.triggerState === 'ACQUIRED') { return " Running "; } else if (row.triggerState === 'PAUSED') { return " Pause "; } else { return " Unknown status "; } }, // Read data from the server loadData: function (currentPage, pageSize) { this.loading = true; this.$http.get('job?' + 'currentPage=' + currentPage + '&pageSize=' + pageSize).then(function (res) { console.log(res); this.tableData = res.body.data.list; this.totalCount = res.body.data.total; this.loading = false; }, function () { console.log('failed'); }); }, // Delete task handleDelete: function (index, row) { this.$http.delete('job', { params: { "jobClassName": row.jobName, "jobGroupName": row.jobGroup } }, { emulateJSON: true}).then(function (res) { this.loadData(this.currentPage, this.pagesize); }, function () { console.log('failed'); }); }, // Suspend task handlePause: function (index, row) { this.$http.put('job?pause', { "jobClassName": row.jobName, "jobGroupName": row.jobGroup }, { emulateJSON: true}).then(function (res) { this.loadData(this.currentPage, this.pagesize); }, function () { console.log('failed'); }); }, // Recovery task handleResume: function (index, row) { this.$http.put('job?resume', { "jobClassName": row.jobName, "jobGroupName": row.jobGroup }, { emulateJSON: true}).then(function (res) { this.loadData(this.currentPage, this.pagesize); }, function () { console.log('failed'); }); }, // Search for search: function () { this.loadData(this.currentPage, this.pagesize); }, // Pop-up dialog box handleadd: function () { this.dialogFormVisible = true; }, // add to add: function () { this.$http.post('job', { "jobName": this.form.jobName, "jobClassName": this.form.jobClassName, "jobGroupName": this.form.jobGroup, "cronExpression": this.form.cronExpression }, { emulateJSON: true}).then(function (res) { this.loadData(this.currentPage, this.pagesize); this.dialogFormVisible = false; }, function () { console.log('failed'); }); }, // to update handleUpdate: function (index, row) { console.log(row); this.updateFormVisible = true; this.updateform.jobName = row.jobName; this.updateform.jobGroup = row.jobGroup; }, // Update task update: function () { this.$http.put('job?cron', { "jobClassName": this.updateform.jobName, "jobGroupName": this.updateform.jobGroup, "cronExpression": this.updateform.cronExpression }, { emulateJSON: true} ).then(function (res) { this.loadData(this.currentPage, this.pagesize); this.updateFormVisible = false; }, function () { console.log('failed'); }); }, // The amount of data displayed on each page changes handleSizeChange: function (val) { this.pagesize = val; this.loadData(this.currentPage, this.pagesize); }, // Page number change handleCurrentChange: function (val) { this.currentPage = val; this.loadData(this.currentPage, this.pagesize); } } }); // Load data vue.loadData(vue.currentPage, vue.pagesize); </script> </body> </html>
8.3 about 7.4 Optimized code and Download address
8.3.1 Optimized code
1. JobService.java
- as follows :
package com.liu.susu.service.task; import com.liu.susu.common.ResultData; import com.liu.susu.pojo.entity.sys.SysJobManagerEntity; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import java.util.List; public interface JobService { /** * Query the scheduled task list */ List<JobAndTriggerVo> selectAllJobList(); /** * Add and start scheduled tasks */ void addJob(SysJobManagerEntity form) throws Exception; /** * Pause scheduled tasks */ ResultData pauseJob(String jobNameKey, String jobGroupNameCode); /** * Resume scheduled tasks */ ResultData resumeJob(String jobNameKey, String jobGroupNameCode) ; /** * Reconfigure scheduled tasks */ ResultData updateJobCron(String jobNameKey, String jobGroupNameCode,String newCron) ; /** * Delete scheduled tasks */ ResultData deleteJob(String jobNameKey, String jobGroupNameCode); }
2. JobServiceImpl.java
- as follows :
package com.liu.susu.service.task.impl; import com.liu.susu.common.ResultData; import com.liu.susu.common.ReturnCode; import com.liu.susu.mapper.task.JobMapper; import com.liu.susu.pojo.entity.sys.SysJobManagerEntity; import com.liu.susu.service.task.JobService; import com.liu.susu.task.quartz.vobo.vo.JobAndTriggerVo; import com.liu.susu.utils.JobUtil; import lombok.extern.slf4j.Slf4j; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service @Slf4j public class JobServiceImpl implements JobService { @Autowired private Scheduler scheduler; @Autowired private JobMapper jobMapper; /** * Query the scheduled task list */ @Override public List<JobAndTriggerVo> selectAllJobList() { return jobMapper.list(); } /** * Add and start scheduled tasks */ @Override public void addJob(SysJobManagerEntity form) throws Exception { // Start the scheduler scheduler.start(); // structure Job Information JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()) .withIdentity(form.getJobNameKey(), form.getJobGroupNameCode()).build(); // Cron Expression scheduling builder ( That is, the time of task execution ) CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getJobCron()); // according to Cron Expression builds a Trigger CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(form.getJobNameKey(), form.getJobGroupNameCode()) .withSchedule(cron).build(); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { log.error("【 Timing task 】 Create failure !", e); throw new Exception("【 Timing task 】 Create failure !"); } } /** * Pause scheduled tasks */ @Override public ResultData pauseJob(String jobNameKey, String jobGroupNameCode) { try { scheduler.pauseJob(JobKey.jobKey(jobNameKey, jobGroupNameCode)); return new ResultData(ReturnCode.SUCCESS_000000," Pause succeeded !"); } catch (SchedulerException e) { e.printStackTrace(); return new ResultData(ReturnCode.FAIL_999999); } } /** * Resume scheduled tasks */ @Override public ResultData resumeJob(String jobNameKey, String jobGroupNameCode) { try { scheduler.resumeJob(JobKey.jobKey(jobNameKey, jobGroupNameCode)); return new ResultData(ReturnCode.SUCCESS_000000," The scheduled task is restored successfully !"); } catch (SchedulerException e) { e.printStackTrace(); return new ResultData(ReturnCode.FAIL_999999); } } /** * Modify scheduled tasks */ @Override public ResultData updateJobCron(String jobNameKey, String jobGroupNameCode,String newCron) { try { TriggerKey triggerKey = TriggerKey.triggerKey(jobNameKey, jobGroupNameCode); // Expression scheduling builder CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(newCron); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // according to Cron Expression builds a Trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); // Press new trigger To reset job perform scheduler.rescheduleJob(triggerKey, trigger); return new ResultData(ReturnCode.UPDATE_SUCCESS," The scheduled task is modified successfully !"); } catch (SchedulerException e) { log.error("【 Timing task 】 Update failed !", e); e.printStackTrace(); return new ResultData(ReturnCode.FAIL_999999); } } /** * Delete scheduled tasks */ @Override public ResultData deleteJob(String jobNameKey, String jobGroupNameCode) { try { scheduler.pauseTrigger(TriggerKey.triggerKey(jobNameKey, jobGroupNameCode)); scheduler.unscheduleJob(TriggerKey.triggerKey(jobNameKey, jobGroupNameCode)); scheduler.deleteJob(JobKey.jobKey(jobNameKey, jobGroupNameCode)); return new ResultData(ReturnCode.DELETE_SUCCESS," Scheduled task deleted successfully !"); } catch (SchedulerException e) { e.printStackTrace(); return new ResultData(ReturnCode.FAIL_999999); } } }
3.JobController2.java
- as follows :
package com.liu.susu.controller.task;
import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liu.susu.common.PageParam;
import com.liu.susu.common.ResultData;
import com.liu.susu.common.ReturnCode;
import com.liu.susu.mapper.task.SysJobManagerMapper;
import com.liu.susu.pojo.entity.sys.SysJobManagerEntity;
import com.liu.susu.service.task.JobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Controller
@RequestMapping("/sys/quartz/task")
@Api(tags = " System management --> Timed task management ")
@ApiSupport(author = " Ride the wind and waves ",order = 3)
@Slf4j
public class JobController2 {
@Autowired
private JobService jobService;
@Autowired
private SysJobManagerMapper sysJobManagerMapper;
@ApiOperationSupport(author = " Ride the wind and waves ",order = 1)
@ApiOperation(value = " Query the scheduled task list ")
@PostMapping("/selectAllJob")
@ResponseBody
public ResultData selectAllJob(@Valid PageParam pageParam) {
if (pageParam!=null){
PageHelper.startPage(pageParam.getPageNum(),pageParam.getPageSize());
}
return ResultData.getPageBaseResultData(pageParam,jobService.selectAllJobList());
}
@ApiOperationSupport(author = " Ride the wind and waves ",order = 2)
@ApiOperation(value = " Add a scheduled task ")
@PostMapping("/addNewJob")
@ResponseBody
public ResultData addNewJob(@RequestBody SysJobManagerEntity form) {
if (form!=null && StringUtils.isNotEmpty(form.getJobGroupNameCode())
&& StringUtils.isNotEmpty(form.getJobNameKey())){
// Before adding tasks , First verify whether there is maintenance in the list that can be added
int count = sysJobManagerMapper.findSysJobManager(form.getJobGroupNameCode(), form.getJobNameKey());
if (count>0){
try {
jobService.addJob(form);
return new ResultData(ReturnCode.INSERT_SUCCESS);
} catch (Exception e) {
return new ResultData(ReturnCode.FAIL_999999);
}
}else {
return new ResultData(ReturnCode.FAIL_999998," The scheduled task to be added is not maintained , Please contact the administrator to maintain !");
}
}
return new ResultData(ReturnCode.FAIL_NO_PARAM, " The form parameter is empty , Please check the parameters ");
}
@ApiOperationSupport(author = " Ride the wind and waves ",order = 3)
@ApiOperation(value = " Suspend task ")
@GetMapping("/pauseJob")
@ResponseBody
public ResultData pauseJob(@RequestParam(value = "jobNameKey",required = true) String jobNameKey,
@RequestParam(value = "jobGroupNameCode",required = true) String jobGroupNameCode){
if (StringUtils.isEmpty(jobNameKey) || StringUtils.isEmpty(jobGroupNameCode)){
return new ResultData(ReturnCode.FAIL_NO_PARAM, " The parameter cannot be null !");
}
return jobService.pauseJob(jobNameKey,jobGroupNameCode);
}
@ApiOperationSupport(author = " Ride the wind and waves ",order = 4)
@ApiOperation(value = " Resume scheduled tasks ")
@GetMapping("/resumeJob")
@ResponseBody
public ResultData resumeJob(@RequestParam(value = "jobNameKey") String jobNameKey,
@RequestParam(value = "jobGroupNameCode") String jobGroupNameCode) {
if (StringUtils.isEmpty(jobNameKey) || StringUtils.isEmpty(jobGroupNameCode)){
return new ResultData(ReturnCode.FAIL_NO_PARAM, " The parameter cannot be null !");
}
return jobService.resumeJob(jobNameKey,jobGroupNameCode);
}
@ApiOperationSupport(author = " Ride the wind and waves ",order = 5)
@ApiOperation(value = " Modify scheduled tasks , Timing time ")
@GetMapping("/updateJobCron")
@ResponseBody
public ResultData updateJobCron(@Param("jobNameKey") String jobNameKey,
@Param("jobGroupNameCode") String jobGroupNameCode,
@Param("cron") String newCron) {
return jobService.updateJobCron(jobNameKey, jobGroupNameCode, newCron);
}
@ApiOperationSupport(author = " Ride the wind and waves ",order = 6)
@ApiOperation(value = " Delete scheduled tasks ")
@GetMapping("/deleteJob")
@ResponseBody
public ResultData deleteJob(@Param("jobNameKey") String jobNameKey,
@Param("jobGroupNameCode") String jobGroupNameCode) {
jobService.deleteJob(jobNameKey,jobGroupNameCode);
return new ResultData(ReturnCode.DELETE_SUCCESS, " Delete successful !");
}
}
8.3.2 Download address
I integrated this into my project , The optimized code is also , Too much code , So I posted part of the code above , Others can be downloaded by themselves as needed :
边栏推荐
- 路由中的生命周期钩子 - activated与deactivated
- Use vscode to configure Mysql to realize connection, query, and other functions
- JS chicken laying eggs and egg laying chickens. Who appeared earlier, object or function? Is function an instance of function?
- 聊天机器人有何用处?有何类型?看完这些就明白了!
- Vscode remote debugging PHP solution through remotessh and Xdebug
- [C language brush leetcode] 1054. Bar code with equal distance (m)
- 20-40k | mecarmand 3D vision algorithm / software / Product Manager Recruitment
- 建木持续集成平台v2.5.2发布
- 城市花样精~侬好!DESIGN#可视化电台即将开播
- Vite3.0 has been released, can you still roll it (list of new features)
猜你喜欢

ERROR 1045 (28000) Access denied for user ‘root‘@‘localhost‘解决方法

H3C_ Using setting default static routing priority to realize the active and standby function of export dual lines

js中break与continue和return关键字

VMware16创建虚拟机:Win11无法安装

JS 鸡生蛋与蛋生鸡问题,Object与Function究竟谁出现的更早?Function算不算Function的实例?

Improved pillar with fine grained feature for 3D object detection paper notes

Nodejs installation tutorial

数组的子集能否累加出K

leetcode力扣经典问题——4.寻找两个正序数组的中位数

Docker最新超详细教程——Docker创建运行MySQL并挂载
随机推荐
Remote invocation of microservices
fillder使用
我的个人网站不让接入微信登录,于是我做了这个
做开发4年13K,想转行自动化测试,薪资还能涨吗···
Operator3-设计一个operator
H3C_利用设置缺省静态路由优先级实现出口双线路的主备功能
leetcode力扣经典问题——4.寻找两个正序数组的中位数
Excel file reading and writing (creation and parsing)
MySQL 高级(进阶) SQL 语句 (一)
Gin parameter validation
WPF interface layout must know basis
Redis基础篇
Error 1045 (28000) access denied for user 'root' @ 'localhost' solution
对Vintage分析的一些学习理解
聊天机器人有何用处?有何类型?看完这些就明白了!
Vite3.0都发布了,你还能卷得动吗(新特性一览)
数组的子集不能累加出的最小正数
Vmware16 create virtual machine: win11 cannot be installed
建木持续集成平台v2.5.2发布
WPF 界面布局必知基础