十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專(zhuān)業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
這篇文章將為大家詳細(xì)講解有關(guān)SpringBoot如何實(shí)現(xiàn)動(dòng)態(tài)控制定時(shí)任務(wù)支持多參數(shù)功能,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的嘉峪關(guān)網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
由于工作上的原因,需要進(jìn)行定時(shí)任務(wù)的動(dòng)態(tài)增刪改查,網(wǎng)上大部分資料都是整合quertz框架實(shí)現(xiàn)的。本人查閱了一些資料,發(fā)現(xiàn)springBoot本身就支持實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)控制。并進(jìn)行改進(jìn),現(xiàn)支持任意多參數(shù)定時(shí)任務(wù)配置
實(shí)現(xiàn)結(jié)果如下圖所示:
后臺(tái)測(cè)試顯示如下:
github 簡(jiǎn)單demo地址如下:
springboot-dynamic-task
1.定時(shí)任務(wù)的配置類(lèi):SchedulingConfig
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: 定時(shí)任務(wù)配置類(lèi) * @author: CaoTing * @date: 2019/5/23 **/ @Configuration public class SchedulingConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // 定時(shí)任務(wù)執(zhí)行線程池核心線程數(shù) taskScheduler.setPoolSize(4); taskScheduler.setRemoveOnCancelPolicy(true); taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-"); return taskScheduler; } }
2.定時(shí)任務(wù)注冊(cè)類(lèi):CronTaskRegistrar
這個(gè)類(lèi)包含了新增定時(shí)任務(wù),移除定時(shí)任務(wù)等等核心功能方法
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: 添加定時(shí)任務(wù)注冊(cè)類(lèi),用來(lái)增加、刪除定時(shí)任務(wù)。 * @author: CaoTing * @date: 2019/5/23 **/ @Component public class CronTaskRegistrar implements DisposableBean { private final MapscheduledTasks = new ConcurrentHashMap<>(16); @Autowired private TaskScheduler taskScheduler; public TaskScheduler getScheduler() { return this.taskScheduler; } /** * 新增定時(shí)任務(wù) * @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)); } } /** * 移除定時(shí)任務(wù) * @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(); } }
3.定時(shí)任務(wù)執(zhí)行類(lèi):SchedulingRunnable
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: 定時(shí)任務(wù)運(yùn)行類(lèi) * @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("定時(shí)任務(wù)開(kāi)始執(zhí)行 - bean:{},方法:{},參數(shù):{}", 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("定時(shí)任務(wù)執(zhí)行異常 - bean:%s,方法:%s,參數(shù):%s ", beanName, methodName, params), ex); } long times = System.currentTimeMillis() - startTime; logger.info("定時(shí)任務(wù)執(zhí)行結(jié)束 - bean:{},方法:{},參數(shù):{},耗時(shí):{} 毫秒", 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.定時(shí)任務(wù)控制類(lèi):ScheduledTask
import java.util.concurrent.ScheduledFuture; /** * @program: simple-demo * @description: 定時(shí)任務(wù)控制類(lèi) * @author: CaoTing * @date: 2019/5/23 **/ public final class ScheduledTask { public volatile ScheduledFuture> future; /** * 取消定時(shí)任務(wù) */ public void cancel() { ScheduledFuture> future = this.future; if (future != null) { future.cancel(true); } } }
5.定時(shí)任務(wù)的測(cè)試
編寫(xiě)一個(gè)需要用于測(cè)試的任務(wù)類(lèi)
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("這是有參示例任務(wù):" + param1 + param2); } public void taskNoParams() { System.out.println("這是無(wú)參示例任務(wù)"); } }
進(jìn)行單元測(cè)試
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: 測(cè)試定時(shí)任務(wù) * @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.工具類(lèi):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工具類(lèi) * @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; } //通過(guò)name獲取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } //通過(guò)class獲取Bean. public staticT getBean(Class clazz) { return getApplicationContext().getBean(clazz); } //通過(guò)name,以及Clazz返回指定的Bean public static T getBean(String name, Class clazz) { return getApplicationContext().getBean(name, clazz); } }
7.我的pom依賴
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
springboot一種全新的編程規(guī)范,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程,SpringBoot也是一個(gè)服務(wù)于框架的框架,服務(wù)范圍是簡(jiǎn)化配置文件。
關(guān)于“SpringBoot如何實(shí)現(xiàn)動(dòng)態(tài)控制定時(shí)任務(wù)支持多參數(shù)功能”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。