摘要:由于工作上的原因,需要进行定时任务的动态增删改查,网上大部分资料都是整合框架实现的。本人查阅了一些资料,发现本身就支持实现定时任务的动态控制。
由于工作上的原因,需要进行定时任务的动态增删改查,网上大部分资料都是整合quertz框架实现的。本人查阅了一些资料,发现springBoot本身就支持实现定时任务的动态控制。并进行改进,现支持任意多参数定时任务配置
实现结果如下图所示:
后台测试显示如下:
github 简单demo地址如下:
springboot-dynamic-task
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** * @program: simple-demo * @description: 定时任务配置类 * @author: CaoTing * @date: 2019/5/23 **/ @Configuration public class SchedulingConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // 定时任务执行线程池核心线程数 taskScheduler.setPoolSize(4); taskScheduler.setRemoveOnCancelPolicy(true); taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-"); return taskScheduler; } }2.定时任务注册类:CronTaskRegistrar
这个类包含了新增定时任务,移除定时任务等等核心功能方法
import com.caotinging.demo.task.ScheduledTask; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.config.CronTask; import org.springframework.stereotype.Component; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @program: simple-demo * @description: 添加定时任务注册类,用来增加、删除定时任务。 * @author: CaoTing * @date: 2019/5/23 **/ @Component public class CronTaskRegistrar implements DisposableBean { private final Map3.定时任务执行类:SchedulingRunnablescheduledTasks = new ConcurrentHashMap<>(16); @Autowired private TaskScheduler taskScheduler; public TaskScheduler getScheduler() { return this.taskScheduler; } /** * 新增定时任务 * @param task * @param cronExpression */ public void addCronTask(Runnable task, String cronExpression) { addCronTask(new CronTask(task, cronExpression)); } public void addCronTask(CronTask cronTask) { if (cronTask != null) { Runnable task = cronTask.getRunnable(); if (this.scheduledTasks.containsKey(task)) { removeCronTask(task); } this.scheduledTasks.put(task, scheduleCronTask(cronTask)); } } /** * 移除定时任务 * @param task */ public void removeCronTask(Runnable task) { ScheduledTask scheduledTask = this.scheduledTasks.remove(task); if (scheduledTask != null) scheduledTask.cancel(); } public ScheduledTask scheduleCronTask(CronTask cronTask) { ScheduledTask scheduledTask = new ScheduledTask(); scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger()); return scheduledTask; } @Override public void destroy() { for (ScheduledTask task : this.scheduledTasks.values()) { task.cancel(); } this.scheduledTasks.clear(); } }
import com.caotinging.demo.utils.SpringContextUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; import java.util.Objects; /** * @program: simple-demo * @description: 定时任务运行类 * @author: CaoTing * @date: 2019/5/23 **/ public class SchedulingRunnable implements Runnable { private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class); private String beanName; private String methodName; private Object[] params; public SchedulingRunnable(String beanName, String methodName) { this(beanName, methodName, null); } public SchedulingRunnable(String beanName, String methodName, Object...params ) { this.beanName = beanName; this.methodName = methodName; this.params = params; } @Override public void run() { logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanName, methodName, params); long startTime = System.currentTimeMillis(); try { Object target = SpringContextUtils.getBean(beanName); Method method = null; if (null != params && params.length > 0) { Class>[] paramCls = new Class[params.length]; for (int i = 0; i < params.length; i++) { paramCls[i] = params[i].getClass(); } method = target.getClass().getDeclaredMethod(methodName, paramCls); } else { method = target.getClass().getDeclaredMethod(methodName); } ReflectionUtils.makeAccessible(method); if (null != params && params.length > 0) { method.invoke(target, params); } else { method.invoke(target); } } catch (Exception ex) { logger.error(String.format("定时任务执行异常 - bean:%s,方法:%s,参数:%s ", beanName, methodName, params), ex); } long times = System.currentTimeMillis() - startTime; logger.info("定时任务执行结束 - bean:{},方法:{},参数:{},耗时:{} 毫秒", beanName, methodName, params, times); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SchedulingRunnable that = (SchedulingRunnable) o; if (params == null) { return beanName.equals(that.beanName) && methodName.equals(that.methodName) && that.params == null; } return beanName.equals(that.beanName) && methodName.equals(that.methodName) && params.equals(that.params); } @Override public int hashCode() { if (params == null) { return Objects.hash(beanName, methodName); } return Objects.hash(beanName, methodName, params); } }4.定时任务控制类:ScheduledTask
import java.util.concurrent.ScheduledFuture; /** * @program: simple-demo * @description: 定时任务控制类 * @author: CaoTing * @date: 2019/5/23 **/ public final class ScheduledTask { public volatile ScheduledFuture> future; /** * 取消定时任务 */ public void cancel() { ScheduledFuture> future = this.future; if (future != null) { future.cancel(true); } } }5.定时任务的测试
编写一个需要用于测试的任务类
import org.springframework.stereotype.Component; /** * @program: simple-demo * @description: * @author: CaoTing * @date: 2019/5/23 **/ @Component("demoTask") public class DemoTask { public void taskWithParams(String param1, Integer param2) { System.out.println("这是有参示例任务:" + param1 + param2); } public void taskNoParams() { System.out.println("这是无参示例任务"); } }
进行单元测试
import com.caotinging.demo.application.DynamicTaskApplication; import com.caotinging.demo.application.SchedulingRunnable; import com.caotinging.demo.config.CronTaskRegistrar; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @program: simple-demo * @description: 测试定时任务 * @author: CaoTing * @date: 2019/5/23 **/ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = DynamicTaskApplication.class) public class TaskTest { @Autowired CronTaskRegistrar cronTaskRegistrar; @Test public void testTask() throws InterruptedException { SchedulingRunnable task = new SchedulingRunnable("demoTask", "taskNoParams", null); cronTaskRegistrar.addCronTask(task, "0/10 * * * * ?"); // 便于观察 Thread.sleep(3000000); } @Test public void testHaveParamsTask() throws InterruptedException { SchedulingRunnable task = new SchedulingRunnable("demoTask", "taskWithParams", "haha", 23); cronTaskRegistrar.addCronTask(task, "0/10 * * * * ?"); // 便于观察 Thread.sleep(3000000); } }6.工具类:SpringContextUtils
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * @program: simple-demo * @description: spring获取bean工具类 * @author: CaoTing * @date: 2019/5/23 **/ @Component public class SpringContextUtils implements ApplicationContextAware { private static ApplicationContext applicationContext = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringContextUtils.applicationContext == null) { SpringContextUtils.applicationContext = applicationContext; } } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //通过name获取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } //通过class获取Bean. public static7.我的pom依赖T getBean(Class clazz) { return getApplicationContext().getBean(clazz); } //通过name,以及Clazz返回指定的Bean public static T getBean(String name, Class clazz) { return getApplicationContext().getBean(name, clazz); } }
8.总结org.springframework.boot spring-boot-starter-jdbc com.baomidou mybatisplus-spring-boot-starter 1.0.5 com.baomidou mybatis-plus 2.1.9 mysql mysql-connector-java runtime com.alibaba druid-spring-boot-starter 1.1.9 org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test provided org.springframework.boot spring-boot-starter-data-redis redis.clients jedis 2.7.3 org.apache.httpcomponents httpclient org.apache.httpcomponents httpclient-cache org.projectlombok lombok true com.alibaba fastjson 1.2.31 org.apache.commons commons-lang3 commons-lang commons-lang 2.6 com.google.guava guava 10.0.1 com.belerweb pinyin4j 2.5.0
建议移步github获取简单demo上手实践哦,在本文文首哦。有帮助的话点个赞吧,笔芯。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74724.html
摘要:也是自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。 原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10659045.html,否则将追究法律责任!!! 一、在JAVA开发领域,目前可以通过以下几种方式进行定时任务 1、单机部署模式 Timer:jdk中...
摘要:本文使用实现对定时任务的增删改查启用停用等功能。并把定时任务持久化到数据库以及支持集群。决定什么时候来执行任务。定义的是任务数据,而真正的执行逻辑是在中。封装定时任务接口添加一个暂停恢复删除修改暂停所有恢复所有 简介 Quartz是一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度。本文使用Springboot+Myba...
摘要:而我这里定时任务的触发是要通过接口的方式来触发,所以只用实现以下的调度器即可。我这里简单说下任务的调度器,具体的任务类,触发器,任务什么时候执行是由它决定的。遇到的坑解决方式这个是因为不兼容的问题,所以使用是不会出现这个错误的。 实现定时任务的几种方式: 1.使用linux的crontab 优点: 1.使用方式很简单,只要在crontab中写好 2.随时可以修改,不需要...
阅读 3038·2023-04-26 00:40
阅读 2370·2021-09-27 13:47
阅读 4131·2021-09-07 10:22
阅读 2950·2021-09-06 15:02
阅读 3289·2021-09-04 16:45
阅读 2449·2021-08-11 10:23
阅读 3581·2021-07-26 23:38
阅读 2886·2019-08-30 15:54