demand
You can dynamically add scheduled tasks without restarting services
The effect
Start the project (with an existing scheduled task)
Example Add a scheduled task
View console (dynamic add time task)
Implementation steps
Pom.xml introduces dependencies
Many dependencies can be removed by themselves, mainly: spring-boot-starter-Quartz
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4. RELEASE</version>
<relativePath/> <! -- lookup parent from repository -->
</parent>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-job-quickstart</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
<name>mybatis-plus-job-quickstart</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<! --mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
<scope>runtime</scope>
</dependency>
<! -- Quartz timed task -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<! -- Swagger API -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.3</version>
</dependency>
<! -- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<! -- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
Yml adds thread pool configuration
Task: pool size:10# maximum number of threads max-pool-size:30Keep-alive-seconds: keep-alive-seconds60# queue-capacity:50
Copy the code
Database file
/* Navicat MySQL Data Transfer Source Server: Source Server Version: 80016 Source Host: 127.0.0.1:3306 Source Database: Job Target Server Type: MYSQL Target Server Version: 80016 File Encoding: 65001 Date: 2020-10-21 17:52:45 */
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for quartz_job
-- ----------------------------
DROP TABLE IF EXISTS `quartz_job`;
CREATE TABLE `quartz_job` (
`id` varchar(36) NOT NULL,
`bean_name` varchar(32) DEFAULT NULL COMMENT 'Spring Bean Name ',
`cron_expression` varchar(32) DEFAULT NULL COMMENT 'Cron expression',
`is_pause` int(11) DEFAULT NULL COMMENT 'Status: 1 suspended, 0 enabled',
`job_name` varchar(32) DEFAULT NULL COMMENT 'Task Name',
`method_name` varchar(32) DEFAULT NULL COMMENT 'Method name',
`params` varchar(500) DEFAULT NULL COMMENT 'parameters',
`remark` varchar(500) DEFAULT NULL COMMENT 'note',
`update_time` datetime DEFAULT NULL COMMENT 'Created or updated date'.PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of quartz_job
-- ----------------------------
INSERT INTO `quartz_job` VALUES ('1318039441581010946'.'visitsTask'.'0/1 * * * * ?'.'0'.'Update Traffic'.'run'.'1318039441581010946'.'Test data'.'the 2020-10-19 13:51:07');
INSERT INTO `quartz_job` VALUES ('1318852329113763842'.'visitsTask'.'0/1 * * * * ?'.'0'.'New timing'.'run'.'000001'.'test'.null);
-- ----------------------------
-- Table structure for quartz_log
-- ----------------------------
DROP TABLE IF EXISTS `quartz_log`;
CREATE TABLE `quartz_log` (
`id` varchar(36) NOT NULL,
`baen_name` varchar(200) DEFAULT NULL COMMENT 'Bean name',
`create_time` datetime DEFAULT NULL COMMENT 'Creation date',
`cron_expression` varchar(32) DEFAULT NULL COMMENT 'Cron expression',
`exception_detail` longtext COMMENT 'Exception detail',
`is_success` int(11) DEFAULT NULL COMMENT 'Status 1: successful 0: failed',
`job_name` varchar(200) DEFAULT NULL COMMENT 'Task Name',
`method_name` varchar(200) DEFAULT NULL COMMENT 'Method name',
`params` varchar(200) DEFAULT NULL COMMENT 'parameters',
`time` bigint(20) DEFAULT NULL COMMENT 'Elapsed time (ms)'.PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of quartz_log
-- ----------------------------
INSERT INTO `quartz_log` VALUES ('1318832884848824321'.'visitsTask'.null.'0/1 * * * * ?'.'Executed successfully'.'1'.'Update Traffic'.'run'.'1315548171037986818131039415101946'.'1');
INSERT INTO `quartz_log` VALUES ('1318832888502063106'.'visitsTask'.null.'0/1 * * * * ?'.'Executed successfully'.'1'.'Update Traffic'.'run'.'1315548171037986818131039415101946'.'2');
INSERT INTO `quartz_log` VALUES ('1318852710766067715'.'visitsTask'.null.'0/1 * * * * ?'.'Executed successfully'.'1'.'New timing'.'run'.'000001'.'1');
INSERT INTO `quartz_log` VALUES ('1318852714960371713'.'visitsTask'.null.'0/1 * * * * ?'.'Executed successfully'.'1'.'Update Traffic'.'run'.'1315548171037986818131039415101946'.'0');
INSERT INTO `quartz_log` VALUES ('1318852714960371714'.'visitsTask'.null.'0/1 * * * * ?'.'Executed successfully'.'1'.'New timing'.'run'.'000001'.'0');
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`email` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL.PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_croatian_ci;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1'.'Jone'.'18'.'[email protected]');
INSERT INTO `user` VALUES ('2'.'Jack'.'20'.'[email protected]');
INSERT INTO `user` VALUES ('3'.'Tom'.'21'.'[email protected]');
INSERT INTO `user` VALUES ('4'.'Sandy'.'22'.'[email protected]');
Copy the code
The code block
package com.mybatisplus.job.threadPool;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/** * Config attribute class */
@Data
@Component
@ConfigurationProperties(prefix = "task.pool")
public class AsyncTaskProperties {
private int corePoolSize;
private int maxPoolSize;
private int keepAliveSeconds;
private int queueCapacity;
}
Copy the code
package com.mybatisplus.job.threadPool;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/** * Custom thread name */
@Component
public class TheadFactoryName implements ThreadFactory {
private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public TheadFactoryName(a) {
this("el-pool");
}
private TheadFactoryName(String name){ SecurityManager s = System.getSecurityManager(); group = (s ! =null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup();// In this case, namePrefix is the name + the number of threads that use this factory to create the pool
this.namePrefix = name +
POOL_NUMBER.getAndIncrement();
}
@Override
public Thread newThread(Runnable r) {
// The name of the thread is namePrefix + -thread- + the number of threads executing in the thread pool
Thread t = new Thread(group, r,
namePrefix + "-thread-"+threadNumber.getAndIncrement(),
0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if(t.getPriority() ! = Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); }returnt; }}Copy the code
package com.mybatisplus.job.threadPool;
import com.mybatisplus.job.SpringContextHolder;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/** * to get a custom thread pool */
public class ThreadPoolExecutorUtil {
public static ThreadPoolExecutor getPoll(a){
AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class);
return new ThreadPoolExecutor(
properties.getCorePoolSize(),
properties.getMaxPoolSize(),
properties.getKeepAliveSeconds(),
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(properties.getQueueCapacity()),
newTheadFactoryName() ); }}Copy the code
package com.mybatisplus.job;
import com.mybatisplus.entity.QuartzJob;
import com.mybatisplus.entity.QuartzLog;
import com.mybatisplus.job.threadPool.ThreadPoolExecutorUtil;
import com.mybatisplus.mapper.QuartzJobMapper;
import com.mybatisplus.mapper.QuartzLogMapper;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;
import javax.annotation.Resource;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
@Async
public class ExecutionJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private static final String JOB_NAME = "TASK_";
@Resource(name = "scheduler")
private Scheduler scheduler;
/** * only for reference */
private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
@Override
@SuppressWarnings("unchecked")
protected void executeInternal(JobExecutionContext context) {
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
// Get the Spring bean
QuartzJobMapper quartzJobMapper = SpringContextHolder.getBean(QuartzJobMapper.class);
QuartzLogMapper quartzLogMapper = SpringContextHolder.getBean(QuartzLogMapper.class);
QuartzLog log = new QuartzLog();
log.setJobName(quartzJob.getJobName());
log.setBaenName(quartzJob.getBeanName());
log.setMethodName("run");
log.setParams(quartzJob.getParams());
long startTime = System.currentTimeMillis();
log.setCronExpression(quartzJob.getCronExpression());
try {
// Execute the task
logger.info("Task ready to execute, task name: {}", quartzJob.getJobName());
QuartzRunnable task = newQuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),quartzJob.getParams()); Future<? > future = EXECUTOR.submit(task); future.get();long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// Task status
log.setIsSuccess(1);
log.setExceptionDetail("Executed successfully");
logger.info("Task completed, task name: {} Total time: {} ms", quartzJob.getJobName(), times);
} catch (Exception e) {
logger.info("Task execution failed. Failure cause {}",e.getMessage());
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// Task status 1: succeeded 0: failed
log.setIsSuccess(0);
log.setExceptionDetail("Timed execution failed");
quartzJob.setIsPause(1);
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
} catch (Exception ee){
logger.info("Failed to suspend scheduled task {}",ee.getMessage());
throw new BadRequestException("Failed to suspend scheduled task");
}
// Update the status
quartzJobMapper.updateById(quartzJob);
} finally{ quartzLogMapper.insert(log); }}}Copy the code
package com.mybatisplus.job;
import com.mybatisplus.entity.QuartzJob;
import com.mybatisplus.entity.QuartzLog;
import com.mybatisplus.job.threadPool.ThreadPoolExecutorUtil;
import com.mybatisplus.mapper.QuartzJobMapper;
import com.mybatisplus.mapper.QuartzLogMapper;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;
import javax.annotation.Resource;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
@Async
public class ExecutionJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private static final String JOB_NAME = "TASK_";
@Resource(name = "scheduler")
private Scheduler scheduler;
/** * only for reference */
private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
@Override
@SuppressWarnings("unchecked")
protected void executeInternal(JobExecutionContext context) {
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
// Get the Spring bean
QuartzJobMapper quartzJobMapper = SpringContextHolder.getBean(QuartzJobMapper.class);
QuartzLogMapper quartzLogMapper = SpringContextHolder.getBean(QuartzLogMapper.class);
QuartzLog log = new QuartzLog();
log.setJobName(quartzJob.getJobName());
log.setBaenName(quartzJob.getBeanName());
log.setMethodName("run");
log.setParams(quartzJob.getParams());
long startTime = System.currentTimeMillis();
log.setCronExpression(quartzJob.getCronExpression());
try {
// Execute the task
logger.info("Task ready to execute, task name: {}", quartzJob.getJobName());
QuartzRunnable task = newQuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),quartzJob.getParams()); Future<? > future = EXECUTOR.submit(task); future.get();long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// Task status
log.setIsSuccess(1);
log.setExceptionDetail("Executed successfully");
logger.info("Task completed, task name: {} Total time: {} ms", quartzJob.getJobName(), times);
} catch (Exception e) {
logger.info("Task execution failed. Failure cause {}",e.getMessage());
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// Task status 1: succeeded 0: failed
log.setIsSuccess(0);
log.setExceptionDetail("Timed execution failed");
quartzJob.setIsPause(1);
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
} catch (Exception ee){
logger.info("Failed to suspend scheduled task {}",ee.getMessage());
throw new BadRequestException("Failed to suspend scheduled task");
}
// Update the status
quartzJobMapper.updateById(quartzJob);
} finally{ quartzLogMapper.insert(log); }}}Copy the code
package com.mybatisplus.job;
import com.mybatisplus.entity.QuartzJob;
import com.mybatisplus.mapper.QuartzJobMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class JobRunner implements ApplicationRunner {
@Autowired
private QuartzJobMapper quartzJobMapper;
@Autowired
private QuartzManage quartzManage;
/** * Reactivate enabled scheduled tasks * when the project starts@param applicationArguments /
*/
@Override
public void run(ApplicationArguments applicationArguments){
printSingleColor("".31.1."-------------------- Inject scheduled task ---------------------");
printSingleColor("".1.1."");
List<QuartzJob> quartzJobs = quartzJobMapper.getList();
quartzJobs.stream().forEach(x ->{
printSingleColor("".32.1."Injection -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - >" + x.getJobName());
printSingleColor("".1.1."");
});
quartzJobs.forEach(quartzManage::addJob);
printSingleColor("".34.1."-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- timing injection task -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
printSingleColor("".1.1."");
}
/ * * * *@paramSuch as "==============" *@paramColor code: background color code (41-46); Foreground code (31-36) *@paramN Number +m: 1 bold; 3 in italics; 4 underline *@paramContent Content to print */
public static void printSingleColor(String pattern,int code,int n,String content){
System.out.format("%s\33[%d;%dm%s%n", pattern, code, n, content); }}Copy the code
package com.mybatisplus.job;
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
/** * Scheduled task configuration *@author/ * /
@Configuration
public class QuartzConfig {
/** * Solve the problem of injecting null Spring Bean into Job */
@Component("quartzJobFactory")
public static class QuartzJobFactory extends AdaptableJobFactory {
private final AutowireCapableBeanFactory capableBeanFactory;
public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
this.capableBeanFactory = capableBeanFactory;
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// Call the method of the parent class
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
returnjobInstance; }}/** * Inject scheduler into Spring *@param quartzJobFactory /
* @return Scheduler
* @throws Exception /
*/
@Bean(name = "scheduler")
public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
factoryBean.setJobFactory(quartzJobFactory);
factoryBean.afterPropertiesSet();
Scheduler scheduler=factoryBean.getScheduler();
scheduler.start();
returnscheduler; }}Copy the code
package com.mybatisplus.job;
import com.mybatisplus.entity.QuartzJob;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import static org.quartz.TriggerBuilder.newTrigger;
@Slf4j
@Component
public class QuartzManage {
private static final String JOB_NAME = "TASK_";
@Resource(name = "scheduler")
private Scheduler scheduler;
public void addJob(QuartzJob quartzJob){
try {
// Build job information
JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class).
withIdentity(JOB_NAME + quartzJob.getId()).build();
// Create Trigger with the Trigger name and cron expression
Trigger cronTrigger = newTrigger()
.withIdentity(JOB_NAME + quartzJob.getId())
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()))
.build();
cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);
// Reset the boot time
((CronTriggerImpl)cronTrigger).setStartTime(new Date());
// Perform scheduled tasks
scheduler.scheduleJob(jobDetail,cronTrigger);
// Pause the task
if (quartzJob.getIsPause().equals(1)) { pauseJob(quartzJob); }}catch (Exception e){
log.error(Failed to create a scheduled task, e);
throw new BadRequestException(Failed to create a scheduled task); }}/** * Update the job cron expression *@param quartzJob /
*/
public void updateJobCron(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// Create a scheduled task if it does not exist
if(trigger == null){
addJob(quartzJob);
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
}
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// Reset the boot time
((CronTriggerImpl)trigger).setStartTime(new Date());
trigger.getJobDataMap().put(QuartzJob.JOB_KEY,quartzJob);
scheduler.rescheduleJob(triggerKey, trigger);
// Pause the task
if (quartzJob.getIsPause().equals(1)) { pauseJob(quartzJob); }}catch (Exception e){
log.error("Failed to update the scheduled task", e);
throw new BadRequestException("Failed to update the scheduled task"); }}/** * Delete a job *@param quartzJob /
*/
public void deleteJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
scheduler.deleteJob(jobKey);
} catch (Exception e){
log.error(Failed to delete a scheduled task, e);
throw new BadRequestException(Failed to delete a scheduled task); }}/** * Restore a job *@param quartzJob /
*/
public void resumeJob(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// Create a scheduled task if it does not exist
if(trigger == null) {
addJob(quartzJob);
}
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.resumeJob(jobKey);
} catch (Exception e){
log.error("Failed to restore scheduled task", e);
throw new BadRequestException("Failed to restore scheduled task"); }}/** * Execute job * immediately@param quartzJob /
*/
public void runJobNow(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// Create a scheduled task if it does not exist
if(trigger == null) {
addJob(quartzJob);
}
JobDataMap dataMap = new JobDataMap();
dataMap.put(QuartzJob.JOB_KEY, quartzJob);
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.triggerJob(jobKey,dataMap);
} catch (Exception e){
log.error("Scheduled task execution failed", e);
throw new BadRequestException("Scheduled task execution failed"); }}/** * Suspends a job *@param quartzJob /
*/
public void pauseJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
} catch (Exception e){
log.error("Failed to suspend scheduled task", e);
throw new BadRequestException("Failed to suspend scheduled task"); }}}Copy the code
package com.mybatisplus.job;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
@Slf4j
public class QuartzRunnable implements Callable {
private Object target;
private Method method;
private String params;
QuartzRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException {
this.target = SpringContextHolder.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName); }}@Override
public Object call(a) throws Exception {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
return null; }}Copy the code
package com.mybatisplus.job;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@Slf4j
public class SpringContextHolder implements ApplicationContextAware.DisposableBean {
private static ApplicationContext applicationContext = null;
/** * Takes the Bean from the static variable applicationContext and automatically transforms it to the type of the assigned object
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/** * Takes the Bean from the static variable applicationContext and automatically transforms it to the type of the assigned object
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/** * Check that ApplicationContext is not empty
private static void assertContextInjected(a) {
if (applicationContext == null) {
throw new IllegalStateException("ApplicaitonContext property not injected, please use applicationContext" +
"Define SpringContextHolder in.xml or register SpringContextHolder in the SpringBoot boot class."); }}/** * Clears SpringContextHolder ApplicationContext to Null. */
private static void clearHolder(a) {
log.debug("Clear ApplicationContext in SpringContextHolder :"
+ applicationContext);
applicationContext = null;
}
@Override
public void destroy(a){
SpringContextHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringContextHolder.applicationContext ! =null) {
log.warn("SpringContextHolder ApplicationContext is overwritten. The original ApplicationContext is :"+ SpringContextHolder.applicationContext); } SpringContextHolder.applicationContext = applicationContext; }}Copy the code
package com.mybatisplus.job.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class VisitsTask {
public void run(String str){
log.info("Enter scheduled task -------------------------------> [" + str + "】"); }}Copy the code
Controller
package com.mybatisplus.controller;
import com.mybatisplus.entity.QuartzJob;
import com.mybatisplus.job.QuartzManage;
import com.mybatisplus.mapper.QuartzJobMapper;
import com.mybatisplus.utils.ResponseEntityT;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/ * * *@description: Dynamic timer *@modified By:
* @version: 1.0 $* /
@API (tags=" dynamic timer ")
@RestController
@RequestMapping("/job")
public class JobController {
@Autowired
private QuartzJobMapper quartzJobMapper;
@Autowired
private QuartzManage quartzManage;
/ * * *@return* /
@apiOperation (value=" timer list - list query ", notes=" timer list ")
@GetMapping(value = "/list")
public ResponseEntityT<List<QuartzJob>> queryPageList() {
return ResponseEntityT.OK(quartzJobMapper.getList());
}
/** * add *@param quartzJob
* @return* /
@apiOperation (value=" add ", notes=" add ")
@PostMapping(value = "/add")
publicResponseEntityT<? > add(@RequestBody QuartzJob quartzJob,HttpServletRequest req) {
quartzJob.setIsPause(0);
quartzJobMapper.insert(quartzJob);
quartzManage.addJob(quartzJob);
return ResponseEntityT.OK("Added successfully!");
}
/** * pause/start/delete *@param quartzJob
* @return* /
@apiOperation (value=" pause/start/delete ", notes="isPause = 1 Pause 2. Start now 3. Delete 0. Restore ")
@PutMapping(value = "/edit")
publicResponseEntityT<? > edit(@RequestBody QuartzJob quartzJob) {
QuartzJob findQuartzJob = quartzJobMapper.selectById(quartzJob.getId());
if(quartzJob==null) {
return ResponseEntityT.error("No corresponding data found");
}
if(quartzJob.getIsPause() == 0){
quartzManage.resumeJob(findQuartzJob);
findQuartzJob.setIsPause(0);
quartzJobMapper.updateById(findQuartzJob);
}
if(quartzJob.getIsPause() == 1){
quartzManage.pauseJob(findQuartzJob);
findQuartzJob.setIsPause(1);
quartzJobMapper.updateById(findQuartzJob);
}
if(quartzJob.getIsPause() == 2){
quartzManage.runJobNow(findQuartzJob);
}
if(quartzJob.getIsPause() == 3){
quartzManage.deleteJob(findQuartzJob);
quartzJobMapper.deleteById(findQuartzJob);
}
return ResponseEntityT.OK("Operation successful!"); }}Copy the code