Est-il possible de planifier une méthode de service Spring une seule fois à une heure précise? Par exemple, l'heure actuelle est 14 heures mais lorsque je clique sur le bouton d'action, je souhaite que ma méthode de service commence à 20 heures. Je connais bien les annotations @Scheduled et je ne sais pas comment écrire une expression cron pour ne pas l'exécuter périodiquement. Celui-ci, @Scheduled(cron = "0 0 20 * * ?")
, est déclenché tous les jours à 20 heures.
Aucune suggestion?
Vous pouvez utiliser l'une des implémentations de TaskScheduler de Spring. J'ai fourni un exemple ci-dessous avec un exemple qui ne nécessite pas trop de configuration (ConcurrentTaskScheduler qui encapsule un exécuteur planifié à un seul thread).
La méthode la plus simple est celle nommée schedule qui prend un Runnable et Date seulement. La tâche sera alors exécutée une fois aprèstemps spécifié. Toutes les autres méthodes sont capables de planifier tâches à exécuter à plusieurs reprises.
En savoir plus sur exécution et planification de tâches
Exemple de travail simple:
private TaskScheduler scheduler;
Runnable exampleRunnable = new Runnable(){
@Override
public void run() {
System.out.println("Works");
}
};
@Async
public void executeTaskT() {
ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor();
scheduler = new ConcurrentTaskScheduler(localExecutor);
scheduler.schedule(exampleRunnable,
new Date(1432152000000L));//today at 8 pm UTC - replace it with any timestamp in miliseconds to text
}
...
executeTaskT() //call it somewhere after the spring application has been configured
Remarque:
Pour activer la prise en charge des annotations @Scheduled et @Async, ajoutez @EnableScheduling et @EnableAsync sur l'un de vos @Configuration Des classes
Update - Annulation de la tâche planifiée
La méthode schedule de TaskScheduler renvoie une ScheduledFuture qui est une action portant résultat retardée pouvant être annulée.
Donc, pour l’annuler, vous devez conserver un descripteur pour la tâche planifiée (c’est-à-dire conserver l’objet de retour ScheduledFuture).
Modifications apportées au code ci-dessus pour annuler la tâche:
Déclarez le ScheduledFuture en dehors de votre méthode executeTaskT .
private ScheduledFuture scheduledFuture;
Modifiez votre appel à planifier pour conserver l'objet de retour en tant que tel:
scheduledFuture = scheduler.schedule(exampleRunnable,
new Date(1432152000000L));
Appelez cancel sur l'objet scheduleFuture quelque part dans votre code
boolean mayInterruptIfRunning = true;
scheduledFuture.cancel(mayInterruptIfRunning);
Pour ne pas créer ScheduledExecutorService
et ConcurrentTaskScheduler
à chaque appel de méthode, il est utile d’initialiser TaskScheduler
à la création du service, par exemple.
private final TaskScheduler taskScheduler =
new ConcurrentTaskScheduler(Executors.newScheduledThreadPool(10));
@Async
n'a aucun sens car nous planifions simplement la tâche et quittions la méthode.
Vous pouvez étendre PeriodicTrigger comme suit - il vérifie la dernière heure de complétion: il sera nul si la tâche n'a jamais été exécutée auparavant. Vous pouvez essayer une variante de ceci si vous voulez exécuter la tâche une seule fois à un moment donné.
class RunOnceTrigger extends PeriodicTrigger {
public RunOnceTrigger(long period) {
super(period);
setInitialDelay(period);
}
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
if(triggerContext.lastCompletionTime() == null) { // hasn't executed yet
return super.nextExecutionTime(triggerContext);
}
return null;
}
}