Heim  >  Artikel  >  Java  >  So implementieren Sie dynamische geplante SpringBoot-Aufgaben

So implementieren Sie dynamische geplante SpringBoot-Aufgaben

王林
王林nach vorne
2023-05-21 14:05:301187Durchsuche

Thread-Pool-Konfigurationsklasse zum Ausführen geplanter Aufgaben

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 
@Configuration
public class SchedulingConfig {  
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        // 定时任务执行线程池核心线程数  
        taskScheduler.setPoolSize(6);  
        taskScheduler.setRemoveOnCancelPolicy(true);  
        taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");  
        return taskScheduler;  
    }  
}

Papierklasse von ScheduledFuture

ScheduledFuture ist das Ausführungsergebnis des ScheduledExecutorService-Thread-Pools für geplante Aufgaben.

import java.util.concurrent.ScheduledFuture;
 
public final class ScheduledTask {
  
    volatile ScheduledFuture<?> future;
    /**  
     * 取消定时任务  
     */  
    public void cancel() {  
        ScheduledFuture<?> future = this.future;  
        if (future != null) {  
            future.cancel(true);  
        }  
    }  
}

Ausführbare Schnittstellenimplementierungsklasse

wird vom Thread-Pool der geplanten Aufgabe aufgerufen, um Methoden in der angegebenen Bean auszuführen.

import com.ying.demo.utils.springContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.Objects;
 
public class SchedulingRunnable implements Runnable {
 
   private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class);
 
   private String beanName;
 
   private String methodName;
 
   private String params;
 
   public SchedulingRunnable(String beanName, String methodName) {
      this(beanName, methodName, null);
   }
 
   public SchedulingRunnable(String beanName, String methodName, String 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 (!StringUtils.isEmpty(params)) {
            method = target.getClass().getDeclaredMethod(methodName, String.class);
         } else {
            method = target.getClass().getDeclaredMethod(methodName);
         }
 
         ReflectionUtils.makeAccessible(method);
         if (!StringUtils.isEmpty(params)) {
            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);
   }
}

Registrierungsklasse für zeitgesteuerte Aufgaben

Wird zum Hinzufügen und Löschen zeitgesteuerter Aufgaben verwendet

@Component
public class CronTaskRegistrar implements DisposableBean {
 
   private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);
 
   @Autowired
   private TaskScheduler taskScheduler;
 
   public TaskScheduler getScheduler() {
      return this.taskScheduler;
   }
 
   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));
      }
   }
 
   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();
   }
}

Beispielklasse für zeitgesteuerte Aufgaben

@Slf4j
@Component("taskDemo")
public class Task1 {  
    public void taskByParams(String params) {
        log.info("taskByParams执行时间:{}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        log.info("taskByParams执行有参示例任务:{}",params);
    }  
  
    public void taskNoParams() {
        log.info("taskByParams执行时间:{}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        log.info("taskNoParams执行无参示例任务");
    }
 
    public void test(String params) {
        log.info("test执行时间:{}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        log.info("test执行有参示例任务:{}",params);
    }
}

Datenbanktabellendesign

CREATE TABLE `schedule_setting` (
  `job_id` int NOT NULL AUTO_INCREMENT COMMENT &#39;任务ID&#39;,
  `bean_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT &#39;bean名称&#39;,
  `method_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT &#39;方法名称&#39;,
  `method_params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT &#39;方法参数&#39;,
  `cron_expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT &#39;cron表达式&#39;,
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT &#39;备注&#39;,
  `job_status` int DEFAULT NULL COMMENT &#39;状态(1正常 0暂停)&#39;,
  `create_time` datetime DEFAULT NULL COMMENT &#39;创建时间&#39;,
  `update_time` datetime DEFAULT NULL COMMENT &#39;修改时间&#39;,
  PRIMARY KEY (`job_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Entitätsklasse

@Data
public class ScheduleSetting extends Model<ScheduleSetting> {
   /**
    * 任务ID
    */
   @Id
   private Integer jobId;
   /**
    * bean名称
    */
   private String beanName;
   /**
    * 方法名称
    */
   private String methodName;
   /**
    * 方法参数
    */
   private String methodParams;
   /**
    * cron表达式
    */
   private String cronExpression;
   /**
    * 状态(1正常 0暂停)
    */
   private Integer jobStatus;
   /**
    * 备注
    */
   private String remark;
   /**
    * 创建时间
    */
   private Date createTime;
   /**
    * 更新时间
    */
   private Date updateTime;
}

Aufwärmen für zeitgesteuerte Aufgaben

Nach dem Spring Boot-Projekt ist gestartet, lädt die geplanten Aufgaben in die Datenbank mit normalem Status

cron-Ausdruckssyntax:

[Sekunde] [Minute] [Stunde] [Tag] [Monat] [Woche] [Jahr]

Hinweis: [Jahr] ist kein Pflichtfeld, [Jahr] kann weggelassen werden. es gibt also insgesamt 6. Feld

So implementieren Sie dynamische geplante SpringBoot-Aufgaben

Wildcard-Beschreibung:

* steht für alle Werte. Beispiel: Die Einstellung * im Minutenfeld bedeutet, dass es jede Minute ausgelöst wird.

So implementieren Sie dynamische geplante SpringBoot-Aufgaben? bedeutet, dass kein Wert angegeben ist. Das Verwendungsszenario besteht darin, dass Sie sich nicht um den aktuellen Wert dieses Felds kümmern müssen. Beispiel: Sie möchten am 10. eines jeden Monats einen Vorgang auslösen, aber es ist Ihnen egal, welcher Wochentag es ist. Daher müssen Sie die Position des Feldes für die Woche auf „?“ festlegen 0 0 0 10 * ?

- gibt das Intervall an. Die Einstellung „10-12“ für die Stunde bedeutet beispielsweise, dass sie um 10, 11 und 12 Uhr ausgelöst wird.

  • bedeutet die Angabe mehrerer Werte. Wenn Sie beispielsweise „MON,WED,FRI“ im Wochenfeld festlegen, bedeutet dies, dass die Auslösung am Montag, Mittwoch und Freitag erfolgt.

  • / wird für die inkrementelle Auslösung verwendet. Stellen Sie die Anzahl der Sekunden auf „5/15“ ein, was bedeutet, dass ab der 5. Sekunde alle 15 Sekunden ausgelöst werden (dh die 5. Sekunde, die 20. Sekunde, die 35. Sekunde und die 50. Sekunde). Stellen Sie im Feld „Tag“ „1/3“ ein, um am 1. eines jeden Monats zu beginnen und alle drei Tage auszulösen.

  • L bedeutet das letzte Wort. In der Tagesfeldeinstellung stellt es den letzten Tag des Monats dar (je nach aktuellem Monat hängt es bei Februar auch davon ab, ob es sich um ein Schaltjahr handelt), und im Wochenfeld stellt es den Samstag dar, d. h entspricht „7“ oder „SAT“. Wenn Sie vor „L“ eine Zahl hinzufügen, bedeutet dies die letzte der Daten. Wenn Sie beispielsweise ein Format wie „6L“ im Wochenfeld festlegen, bedeutet dies „der letzte Freitag dieses Monats“.

  • W bedeutet der dem angegebenen Datum am nächsten liegende Arbeitstag (Montag bis Freitag). das Tagesfeld 15W“, das angibt, dass es an dem Werktag ausgelöst wird, der dem 15. eines jeden Monats am nächsten liegt. Wenn der 15. ein Samstag ist, wird der Auslöser am nächsten Freitag (dem 14.) gefunden. Wenn der 15. ein Wochenende ist, wird der Auslöser am nächsten Montag (dem 16.) gefunden B. an einem Werktag (Montag bis Sonntag) 5), wird es an diesem Tag ausgelöst. Wenn das angegebene Format „1W“ ist, bedeutet dies, dass es am nächsten Werktag nach dem 1. eines jeden Monats ausgelöst wird. Fällt der 1. auf einen Samstag, wird er am Montag, den 3. ausgelöst. (Beachten Sie, dass vor „W“ nur bestimmte Zahlen gesetzt werden können und das Intervall „-“ nicht zulässig ist.)

  • # Seriennummer (gibt den Wochentag jedes Monats an). Wenn Sie beispielsweise „6#3“ im Wochenfeld festlegen, bedeutet dies, dass es sich um den dritten Samstag jedes Monats handelt ", es wird der genaue Tag des Monats sein. Wenn es in fünf Wochen keine Samstage gibt, wird diese Konfiguration nicht ausgelöst (ideal für Muttertag und Vatertag); Tipps: „L“ und „W“ können verwendet werden Kombination. Wenn im Feld „Tag“ „LW“ eingestellt ist, bedeutet dies, dass es am letzten Arbeitstag dieses Monats ausgelöst wird; bei der Einstellung des Felds „Woche“ wird die Groß-/Kleinschreibung nicht beachtet, wenn englische Buchstaben verwendet werden, d. h. MON ist dasselbe als Mo.

  • Beispiel:
  • Alle 5 Sekunden ausgeführt: */5 * * * * ?
  • Alle 1 Minute ausgeführt: 0 */1 * * * ?

    Einmal täglich um 23:00 ausgeführt: 0 0 23 * * ?
Einmal jeden Tag um 1 Uhr ausgeführt: 0 0 1 * * ?

Einmal jeden Monat am 1. um 1 Uhr ausgeführt: 0 0 1 1 * ?

Einmal um 23:00 Uhr ausgeführt am letzten Tag jedes Monats: 0 0 23 L * ?

Einmal jeden Samstag um 1 Uhr ausgeführt: 0 0 1 ? * L

Einmal ausgeführt bei 26 Minuten, 29 Minuten und 33 Minuten: 0 26, 29, 33 * * * ?

Einmal täglich um 0:00, 13:00, 18:00 und 21:00 Uhr ausführen: 0 0 0,13,18,21 * * ?

cron Online-Ausdrucksgenerator:

http://tools.jb51.net /code/Quartz_Cron_create

Das obige ist der detaillierte Inhalt vonSo implementieren Sie dynamische geplante SpringBoot-Aufgaben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen