溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringBoot中怎么動(dòng)態(tài)控制定時(shí)任務(wù)

發(fā)布時(shí)間:2021-08-07 15:06:47 來源:億速云 閱讀:173 作者:Leah 欄目:編程語言

SpringBoot中怎么動(dòng)態(tài)控制定時(shí)任務(wù),相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

1.定時(shí)任務(wù)的配置類: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ù)配置類 * @author: CaoTing * @date: 2019/5/23 **/@Configurationpublic 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è)類:CronTaskRegistrar

這個(gè)類包含了新增定時(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è)類,用來增加、刪除定時(shí)任務(wù)。 * @author: CaoTing * @date: 2019/5/23 **/@Componentpublic class CronTaskRegistrar implements DisposableBean {  private final Map<Runnable, ScheduledTask> scheduledTasks = 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í)行類: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)行類 * @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ù)開始執(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ù)控制類:ScheduledTask

import java.util.concurrent.ScheduledFuture;/** * @program: simple-demo * @description: 定時(shí)任務(wù)控制類 * @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ù)的測試

編寫一個(gè)需要用于測試的任務(wù)類

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ù)");  }}

進(jìn)行單元測試

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: 測試定時(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.工具類: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 **/@Componentpublic 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 static <T> T getBean(Class<T> clazz) {    return getApplicationContext().getBean(clazz);  }  //通過name,以及Clazz返回指定的Bean  public static <T> T getBean(String name, Class<T> clazz) {    return getApplicationContext().getBean(name, clazz);  }}

7.我的pom依賴

<dependencies>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-jdbc</artifactId>    </dependency>    <dependency>      <groupId>com.baomidou</groupId>      <artifactId>mybatisplus-spring-boot-starter</artifactId>      <version>1.0.5</version>    </dependency>    <dependency>      <groupId>com.baomidou</groupId>      <artifactId>mybatis-plus</artifactId>      <version>2.1.9</version>    </dependency>    <dependency>      <groupId>mysql</groupId>      <artifactId>mysql-connector-java</artifactId>      <scope>runtime</scope>    </dependency>    <dependency>      <groupId>com.alibaba</groupId>      <artifactId>druid-spring-boot-starter</artifactId>      <version>1.1.9</version>    </dependency>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-aop</artifactId>    </dependency>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <!-- 數(shù)據(jù)庫-->    <!--<dependency>      <groupId>mysql</groupId>      <artifactId>mysql-connector-java</artifactId>      <scope>runtime</scope>    </dependency>-->    <!-- https://mvnrepository.com/artifact/com.hynnet/oracle-driver-ojdbc -->    <!--<dependency>      <groupId>com.oracle</groupId>      <artifactId>ojdbc6</artifactId>      <version>11.2.0.1.0</version>    </dependency>-->    <!-- 單元測試 -->    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-test</artifactId>      <scope>provided</scope>    </dependency>    <!--redisTemplate -->    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-data-redis</artifactId>    </dependency>    <dependency>      <groupId>redis.clients</groupId>      <artifactId>jedis</artifactId>      <version>2.7.3</version>    </dependency>    <!-- http連接 restTemplate -->    <dependency>      <groupId>org.apache.httpcomponents</groupId>      <artifactId>httpclient</artifactId>    </dependency>    <dependency>      <groupId>org.apache.httpcomponents</groupId>      <artifactId>httpclient-cache</artifactId>    </dependency>    <!-- 工具-->    <dependency>      <groupId>org.projectlombok</groupId>      <artifactId>lombok</artifactId>      <optional>true</optional>    </dependency>    <dependency>      <groupId>com.alibaba</groupId>      <artifactId>fastjson</artifactId>      <version>1.2.31</version>    </dependency>    <dependency>      <groupId>org.apache.commons</groupId>      <artifactId>commons-lang3</artifactId>    </dependency>    <dependency>      <groupId>commons-lang</groupId>      <artifactId>commons-lang</artifactId>      <version>2.6</version>    </dependency>    <!-- https://mvnrepository.com/artifact/com.google/guava -->    <dependency>      <groupId>com.google.guava</groupId>      <artifactId>guava</artifactId>      <version>10.0.1</version>    </dependency>    <!-- pinyin4j -->    <dependency>      <groupId>com.belerweb</groupId>      <artifactId>pinyin4j</artifactId>      <version>2.5.0</version>    </dependency>  </dependencies>

看完上述內(nèi)容,你們掌握SpringBoot中怎么動(dòng)態(tài)控制定時(shí)任務(wù)的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI