当前位置:网站首页>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 :
边栏推荐
- 约瑟夫环问题
- [redis] redis development specifications and precautions
- Revolution of game assets
- Implementation of book borrowing management system based on C language
- Guess the number / / generate a random number for the first time
- 彻底搞懂kubernetes调度框架与插件
- MVFuseNet:Improving End-to-End Object Detection and Motion Forecasting through Multi-View Fusion of
- [C language brush leetcode] 1054. Bar code with equal distance (m)
- 数组的子集能否累加出K
- Flink real-time warehouse DWD layer (order placing multiple tables to realize join operation) template code
猜你喜欢

ETL为什么经常变成ELT甚至LET?

Interface test actual project 03: execute test cases

After 4 years of development and 13K, if you want to change to automated testing, can your salary still rise···
![Explanation of suffix automata (SAM) + Luogu p3804 [template] suffix automata (SAM)](/img/8b/f68503e09f218c26e34453b1b7fcd5.png)
Explanation of suffix automata (SAM) + Luogu p3804 [template] suffix automata (SAM)

Implementation of book borrowing management system based on C language

H3C_利用设置缺省静态路由优先级实现出口双线路的主备功能

Problems encountered in vmware16 installing virtual machines

Cvpr2021 | multi view stereo matching based on self supervised learning (cvpr2021)

MySQL----多表查询

VMware16安装虚拟机遇到的问题
随机推荐
第7节-程序的编译(预处理操作)+链接
Redis Basics
Vite3.0 has been released, can you still roll it (list of new features)
利用C语言巧妙实现棋类游戏——三子棋
用户列表 圆形头像并跟随小板块
Vscode remote debugging PHP solution through remotessh and Xdebug
npm install报错npm ERR Could not resolve dependency npm ERR peer
约瑟夫环问题
暑期总结(二)
女研究生做“思维导图”与男友吵架!网友:吵架届的“内卷之王”....
Guess the number / / generate a random number for the first time
【charles日常问题】开启charles,使用不了钉钉
route的meta配置项
OCR光学字符识别方法汇总
LeetCode 879. 盈利计划
WPF 界面布局必知基础
Spark Learning Notes (VII) -- spark core core programming - RDD serialization / dependency / persistence / partition / accumulator / broadcast variables
CAN&CANFD综合测试分析软件LKMaster与PCAN-Explorer 6分析软件的优势对比
buck电路boot电容短路和断路实测波形
Summary of OCR optical character recognition methods