2016-12-16 4 views
1

Ich habe einen geplanten Job im Frühjahr, ich bekomme seine Cron aus meiner Datenbank. Bei jeder Ausführung wird die nächste Ausführungszeit aktualisiert. Wenn es für die Ausführung alle 10 Minuten konfiguriert ist, kann ich den Wert in die Datenbank ändern, um diesen Job alle 15 Minuten zu planen.Spring Update Scheduler

Das Problem ist, dass ich auf die Ausführung warten muss, um den aktualisierten Cron zu erhalten: Wenn ein Job alle 15 Minuten geplant ist und ich diesen Wert alle 2 Minuten ändern möchte, muss ich auf die nächste Ausführung warten (bis zu 15 Minuten), um diesen Job alle 2 Minuten zu haben.

Gibt es eine Möglichkeit, diesen Job nach dem Aktualisieren der Datenbank neu zu planen?

Ich dachte, diese Bean zu zerstören und zu aktualisieren, aber es funktioniert nicht (vielleicht ist es nicht möglich oder etwas war falsch in meiner Implementierung). Vielleicht gibt es eine Möglichkeit, ein Ereignis auszulösen, um die Methode configureTask auszuführen.

Hier der Ausschnitt meines geplanten Jobs.

@EnableScheduling 
@Component 
public class MyClass implements SchedulingConfigurer { 

    private static final String JOB = "My personal task"; 

    @Autowired 
    JobRepository jobRepository; 

    @Override 
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { 
     scheduledTaskRegistrar.addTriggerTask(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("Hello World!"); 
      } 
     }, new Trigger() { 
      @Override 
      public Date nextExecutionTime(TriggerContext triggerContext) { 
       JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB); // read from database 
       String cron = byJobNameIgnoreCase.getCrontab(); 
       CronTrigger trigger = new CronTrigger(cron); 
       return trigger.nextExecutionTime(triggerContext); 
      } 
     }); 
    } 

} 
+0

fand ich diesen Link, aber es funktioniert nicht .. [http://stackoverflow.com/questions/39152599/interrupt-spring-scheduler-task-before-next-invocation?rq=1] –

Antwort

0

Um dies zu verwalten, habe ich einen SchedulerOrchestrator erstellt, der meine Jobs verwaltet. Die Jobs enthalten eine SchedulerFuture.

Hier der Code, ich hoffe, kann jemand anderen helfen.

Lassen Sie uns mit einer Schnittstelle starten, die durch meine Jobs umgesetzt werden:

public interface SchedulerObjectInterface {  
    void start(); 
    void stop(); 
} 

Jeder Job braucht eine ScheduledFuture zu stoppen und muss ein Taskscheduler autowire geplant werden. Hier ist ein Beispiel von einem Job (Sie können so viele erstellen, wie Sie wollen):

@Component 
public class MyFirstJob implements SchedulerObjectInterface { 

    private static final Logger log = LoggerFactory.getLogger(MyFirstJob.class); 

    public static final String JOB = "MyFirstJob"; 

    @Autowired 
    JobRepository jobRepository; 

    private ScheduledFuture future; 

    @Autowired 
    private TaskScheduler scheduler; 


    @Override 
    public void start() { 
     future = scheduler.schedule(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(JOB + " Hello World! " + new Date()); 
      } 
     }, new Trigger() { 
      @Override 
      public Date nextExecutionTime(TriggerContext triggerContext) { 
       String cron = cronConfig(); 
       System.out.println(cron); 
       CronTrigger trigger = new CronTrigger(cron); 
       return trigger.nextExecutionTime(triggerContext); 
      } 
     }); 

    } 

    @Override 
    public void stop() { 
     future.cancel(false); 
    } 

    // retrieve cron from database 
    private String cronConfig() { 
     JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB); 
     return byJobNameIgnoreCase.getCrontab(); 
    } 

} 

Endlich haben wir unsere Arbeit auf eine Orchestrierung hinzufügen:

@Configuration 
public class SchedulerOrchestrator { 

    private static final Logger log = LoggerFactory.getLogger(SchedulerOrchestrator.class); 

    private static Map<String, SchedulerObjectInterface> schduledJobsMap = new HashMap<>(); 

    @Autowired 
    JobRepository jobRepository; 

    @Autowired 
    MyFirstJob myFirstJob; 

    @Autowired 
    MySecondJob mySecondJob; 

    @Autowired 
    TaskScheduler scheduler; 

    @PostConstruct 
    public void initScheduler() { 
     schduledJobsMap.put(MyFirstJob.JOB, myFirstJob); 
     schduledJobsMap.put(MySecondJob.JOB, mySecondJob); 

     startAll(); 
    } 

    public void restart(String job) { 
     stop(job); 
     start(job); 
    } 

    public void stop(String job) { 
     schduledJobsMap.get(job).stop(); 
    } 

    public void start(String job) { 
     schduledJobsMap.get(job).start(); 
    } 

    public void startAll() { 
     for (SchedulerObjectInterface schedulerObjectInterface : schduledJobsMap.values()) { 
      schedulerObjectInterface.start(); 
     } 
    } 

    @Bean 
    public TaskScheduler scheduler() { 
     return new ThreadPoolTaskScheduler(); 
    } 
} 
0

diesen Ansatz in Betracht. Anstatt geplante Aufgaben hinzuzufügen und zu löschen, können Sie jede Minute (oder mit einer anderen Genauigkeit) den tatsächlichen Moment mit Ihren Ansichten vergleichen und erforderliche Aufgaben sofort ausführen. Das wird einfacher. Überprüfen Sie den Quartz Scheduler, dessen CronExpression die Methode isSatisfiedBy (Date date) hat.

@Scheduled(cron = "5 * * * * *) // do not set seconds to zero, cause it may fit xx:yy:59 
public void runTasks() { 
    LocalTime now = LocalTime.now(); // or Date now = new Date(); 
    // check and run 
} 
Verwandte Themen