动态定时任务(动态定时器)

it2025-01-09  43

需求

在不重启服务的情况下,动态添加定时任务

效果

启动项目(有一个已存在的定时任务)

添加一个定时任务

查看控制台(动态添入定时任务)

实现步骤

pom.xml引入依赖

很多无关依赖可以自己删除,主要依赖:spring-boot-starter-quartz

<?xml version="1.0" encoding="UTF-8"?> <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-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定时任务 --> <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>

yml添加线程池配置

task: pool: # 核心线程池大小 core-pool-size: 10 # 最大线程数 max-pool-size: 30 # 活跃时间 keep-alive-seconds: 60 # 队列容量 queue-capacity: 50

数据库文件

/* 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名称', `cron_expression` varchar(32) DEFAULT NULL COMMENT 'cron 表达式', `is_pause` int(11) DEFAULT NULL COMMENT '状态:1暂停、0启用', `job_name` varchar(32) DEFAULT NULL COMMENT '任务名称', `method_name` varchar(32) DEFAULT NULL COMMENT '方法名称', `params` varchar(500) DEFAULT NULL COMMENT '参数', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `update_time` datetime DEFAULT NULL COMMENT '创建或更新日期', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of quartz_job -- ---------------------------- INSERT INTO `quartz_job` VALUES ('1318039441581010946', 'visitsTask', '0/1 * * * * ?', '0', '更新访问量', 'run', '1318039441581010946', '测试数据', '2020-10-19 13:51:07'); INSERT INTO `quartz_job` VALUES ('1318852329113763842', 'visitsTask', '0/1 * * * * ?', '0', '新增定时', 'run', '000001', '测试', 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名称', `create_time` datetime DEFAULT NULL COMMENT '创建日期', `cron_expression` varchar(32) DEFAULT NULL COMMENT 'cron表达式', `exception_detail` longtext COMMENT '异常详细', `is_success` int(11) DEFAULT NULL COMMENT '状态 1:成功 0:失败', `job_name` varchar(200) DEFAULT NULL COMMENT '任务名称', `method_name` varchar(200) DEFAULT NULL COMMENT '方法名称', `params` varchar(200) DEFAULT NULL COMMENT '参数', `time` bigint(20) DEFAULT NULL COMMENT '耗时(毫秒)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of quartz_log -- ---------------------------- INSERT INTO `quartz_log` VALUES ('1318832884848824321', 'visitsTask', null, '0/1 * * * * ?', '执行成功', '1', '更新访问量', 'run', '1315548171037986818,1318039441581010946', '1'); INSERT INTO `quartz_log` VALUES ('1318832888502063106', 'visitsTask', null, '0/1 * * * * ?', '执行成功', '1', '更新访问量', 'run', '1315548171037986818,1318039441581010946', '2'); INSERT INTO `quartz_log` VALUES ('1318852710766067715', 'visitsTask', null, '0/1 * * * * ?', '执行成功', '1', '新增定时', 'run', '000001', '1'); INSERT INTO `quartz_log` VALUES ('1318852714960371713', 'visitsTask', null, '0/1 * * * * ?', '执行成功', '1', '更新访问量', 'run', '1315548171037986818,1318039441581010946', '0'); INSERT INTO `quartz_log` VALUES ('1318852714960371714', 'visitsTask', null, '0/1 * * * * ?', '执行成功', '1', '新增定时', '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', 'test1@baomidou.com'); INSERT INTO `user` VALUES ('2', 'Jack', '20', 'test2@baomidou.com'); INSERT INTO `user` VALUES ('3', 'Tom', '21', 'test3@baomidou.com'); INSERT INTO `user` VALUES ('4', 'Sandy', '22', 'test4@baomidou.com');

 

代码块

package com.mybatisplus.job.threadPool; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 配置属性类 */ @Data @Component @ConfigurationProperties(prefix = "task.pool") public class AsyncTaskProperties { private int corePoolSize; private int maxPoolSize; private int keepAliveSeconds; private int queueCapacity; } package com.mybatisplus.job.threadPool; import org.springframework.stereotype.Component; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * 自定义线程名称 */ @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() { this("el-pool"); } private TheadFactoryName(String name){ SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); //此时namePrefix就是 name + 第几个用这个工厂创建线程池的 this.namePrefix = name + POOL_NUMBER.getAndIncrement(); } @Override public Thread newThread(Runnable r) { //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程 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); } return t; } } 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; /** * 用于获取自定义线程池 */ public class ThreadPoolExecutorUtil { public static ThreadPoolExecutor getPoll(){ AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class); return new ThreadPoolExecutor( properties.getCorePoolSize(), properties.getMaxPoolSize(), properties.getKeepAliveSeconds(), TimeUnit.SECONDS, new ArrayBlockingQueue<>(properties.getQueueCapacity()), new TheadFactoryName() ); } } 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; /** 该处仅供参考 */ private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll(); @Override @SuppressWarnings("unchecked") protected void executeInternal(JobExecutionContext context) { QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); // 获取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 { // 执行任务 logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName()); QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),quartzJob.getParams()); Future<?> future = EXECUTOR.submit(task); future.get(); long times = System.currentTimeMillis() - startTime; log.setTime(times); // 任务状态 log.setIsSuccess(1); log.setExceptionDetail("执行成功"); logger.info("任务执行完毕,任务名称:{} 总共耗时:{} 毫秒", quartzJob.getJobName(), times); } catch (Exception e) { logger.info("任务执行失败,失败原因{}",e.getMessage()); long times = System.currentTimeMillis() - startTime; log.setTime(times); // 任务状态 1:成功 0:失败 log.setIsSuccess(0); log.setExceptionDetail("定时执行失败"); quartzJob.setIsPause(1); try { JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); scheduler.pauseJob(jobKey); } catch (Exception ee){ logger.info("定时任务暂停失败{}",ee.getMessage()); throw new BadRequestException("定时任务暂停失败"); } //更新状态 quartzJobMapper.updateById(quartzJob); } finally { quartzLogMapper.insert(log); } } } 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; /** 该处仅供参考 */ private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll(); @Override @SuppressWarnings("unchecked") protected void executeInternal(JobExecutionContext context) { QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); // 获取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 { // 执行任务 logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName()); QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),quartzJob.getParams()); Future<?> future = EXECUTOR.submit(task); future.get(); long times = System.currentTimeMillis() - startTime; log.setTime(times); // 任务状态 log.setIsSuccess(1); log.setExceptionDetail("执行成功"); logger.info("任务执行完毕,任务名称:{} 总共耗时:{} 毫秒", quartzJob.getJobName(), times); } catch (Exception e) { logger.info("任务执行失败,失败原因{}",e.getMessage()); long times = System.currentTimeMillis() - startTime; log.setTime(times); // 任务状态 1:成功 0:失败 log.setIsSuccess(0); log.setExceptionDetail("定时执行失败"); quartzJob.setIsPause(1); try { JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); scheduler.pauseJob(jobKey); } catch (Exception ee){ logger.info("定时任务暂停失败{}",ee.getMessage()); throw new BadRequestException("定时任务暂停失败"); } //更新状态 quartzJobMapper.updateById(quartzJob); } finally { quartzLogMapper.insert(log); } } } 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; /** * 项目启动时重新激活启用的定时任务 * @param applicationArguments / */ @Override public void run(ApplicationArguments applicationArguments){ printSingleColor("",31,1,"--------------------注入定时任务---------------------"); printSingleColor("",1,1,""); List<QuartzJob> quartzJobs = quartzJobMapper.getList(); quartzJobs.stream().forEach(x ->{ printSingleColor("",32,1,"注入--------------------->" + x.getJobName()); printSingleColor("",1,1,""); }); quartzJobs.forEach(quartzManage::addJob); printSingleColor("",34,1,"--------------------定时任务注入完成---------------------"); printSingleColor("",1,1,""); } /** * * @param pattern 前面的图案 such as "==============" * @param code 颜色代号:背景颜色代号(41-46);前景色代号(31-36) * @param n 数字+m:1加粗;3斜体;4下划线 * @param content 要打印的内容 */ 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); } } 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; /** * 定时任务配置 * @author / */ @Configuration public class QuartzConfig { /** * 解决Job中注入Spring Bean为null的问题 */ @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 { //调用父类的方法 Object jobInstance = super.createJobInstance(bundle); capableBeanFactory.autowireBean(jobInstance); return jobInstance; } } /** * 注入scheduler到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(); return scheduler; } } 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 { // 构建job信息 JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class). withIdentity(JOB_NAME + quartzJob.getId()).build(); //通过触发器名和cron 表达式创建 Trigger Trigger cronTrigger = newTrigger() .withIdentity(JOB_NAME + quartzJob.getId()) .startNow() .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression())) .build(); cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob); //重置启动时间 ((CronTriggerImpl)cronTrigger).setStartTime(new Date()); //执行定时任务 scheduler.scheduleJob(jobDetail,cronTrigger); // 暂停任务 if (quartzJob.getIsPause().equals(1)) { pauseJob(quartzJob); } } catch (Exception e){ log.error("创建定时任务失败", e); throw new BadRequestException("创建定时任务失败"); } } /** * 更新job cron表达式 * @param quartzJob / */ public void updateJobCron(QuartzJob quartzJob){ try { TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 如果不存在则创建一个定时任务 if(trigger == null){ addJob(quartzJob); trigger = (CronTrigger) scheduler.getTrigger(triggerKey); } CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()); trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); //重置启动时间 ((CronTriggerImpl)trigger).setStartTime(new Date()); trigger.getJobDataMap().put(QuartzJob.JOB_KEY,quartzJob); scheduler.rescheduleJob(triggerKey, trigger); // 暂停任务 if (quartzJob.getIsPause().equals(1)) { pauseJob(quartzJob); } } catch (Exception e){ log.error("更新定时任务失败", e); throw new BadRequestException("更新定时任务失败"); } } /** * 删除一个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("删除定时任务失败", e); throw new BadRequestException("删除定时任务失败"); } } /** * 恢复一个job * @param quartzJob / */ public void resumeJob(QuartzJob quartzJob){ try { TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 如果不存在则创建一个定时任务 if(trigger == null) { addJob(quartzJob); } JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); scheduler.resumeJob(jobKey); } catch (Exception e){ log.error("恢复定时任务失败", e); throw new BadRequestException("恢复定时任务失败"); } } /** * 立即执行job * @param quartzJob / */ public void runJobNow(QuartzJob quartzJob){ try { TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 如果不存在则创建一个定时任务 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("定时任务执行失败", e); throw new BadRequestException("定时任务执行失败"); } } /** * 暂停一个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("定时任务暂停失败", e); throw new BadRequestException("定时任务暂停失败"); } } } 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() throws Exception { ReflectionUtils.makeAccessible(method); if (StringUtils.isNotBlank(params)) { method.invoke(target, params); } else { method.invoke(target); } return null; } } 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; /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } /** * 检查ApplicationContext不为空. */ private static void assertContextInjected() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); } } /** * 清除SpringContextHolder中的ApplicationContext为Null. */ private static void clearHolder() { log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); applicationContext = null; } @Override public void destroy(){ SpringContextHolder.clearHolder(); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringContextHolder.applicationContext != null) { log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); } SpringContextHolder.applicationContext = applicationContext; } } 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("进入定时任务 -------------------------------> 【" + str + "】"); } }

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:动态定时器 * @modified By: * @version: 1.0$ */ @Api(tags="动态定时器") @RestController @RequestMapping("/job") public class JobController { @Autowired private QuartzJobMapper quartzJobMapper; @Autowired private QuartzManage quartzManage; /** * @return */ @ApiOperation(value="定时器列表-列表查询", notes="定时器列表") @GetMapping(value = "/list") public ResponseEntityT<List<QuartzJob>> queryPageList() { return ResponseEntityT.OK(quartzJobMapper.getList()); } /** * 添加 * @param quartzJob * @return */ @ApiOperation(value="添加", notes="添加") @PostMapping(value = "/add") public ResponseEntityT<?> add(@RequestBody QuartzJob quartzJob,HttpServletRequest req) { quartzJob.setIsPause(0); quartzJobMapper.insert(quartzJob); quartzManage.addJob(quartzJob); return ResponseEntityT.OK("添加成功!"); } /** * 暂停/启动/删除 * @param quartzJob * @return */ @ApiOperation(value="暂停/启动/删除", notes="isPause = 1 暂停 2.立即启动 3.删除 0.恢复") @PutMapping(value = "/edit") public ResponseEntityT<?> edit(@RequestBody QuartzJob quartzJob) { QuartzJob findQuartzJob = quartzJobMapper.selectById(quartzJob.getId()); if(quartzJob==null) { return ResponseEntityT.error("未找到对应数据"); } 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("操作成功!"); } }

 

源码地址:https://gitee.com/tangzhengfeng_admin/mybatis-plus-job-quickstart

最新回复(0)