schedulerpost

W tym wpisie chciałam przedstawić proces tworzenia planowanych zadań. W Spring Boocie jest to wyjątkowo proste. Nie musimy tworzyć żadnych plików konfiguracyjnych. Wszystko opiera się na dwóch adnotacjach. Przekonajcie się sami.

W pom.xml potrzebujemy tylko i wyłącznie podstawowej zależności startera spring boot’owego.

org.springframework.boot spring-boot-starter 1.4.2.RELEASE

Nasza klasa główna musi mieć adnotację @EnableScheduling

@SpringBootApplication
@EnableScheduling
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(new Object[] { SchedulerApplication.class }, args);
}
}

Teraz przejdźmy do naszej klasy z zadaniami, które mają się wykonywać co określony interwał czasowy. Nad klasą dodajemy adnotację @Component, a nad metodą, która ma być wywoływana dodajemy @Scheduled z odpowiednim parametrem (dostępne parametry opisane poniżej).

@Component
public class ScheduledTask {
private static final Logger log = LoggerFactory.getLogger(ScheduledTask.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat(“HH:mm:ss”);

@Scheduled(fixedRate = 5000)
public void executeTask() {
    log.info("Task executed at {}", dateFormat.format(new Date()));
}

}

Po uruchomieniu naszej aplikacji co 5 sekund w konsoli wyświetlany będzie komunikat z metody executeTask() scheduler

Parametry atrybutu @Scheduled:

1. cron = “0 0 0 * * *“ Parametr ten jest CRON’owym wyrażeniem składającym się z sześciu pól reprezentujących kolejno: sekundy, minuty, godziny, dni miesiąca, miesiące oraz dni tygodnia. Oddzielone są one spacjami. Miesiące i dni tygodnia mogą być podawane jako trzy pierwsze litery ich angielskich nazw lub jako liczby (dni tygodnia liczymy od 1: poniedziałek = 1, wtorek = 2 itd.).

Znak * oznacza każdą wartość, a znak ? oznacza niesprecyzowaną wartość. Użyć możemy jej kiedy np. chcemy wywoływać usługę w każdy piątek miesiąca i nie interesuje nas jakie to będą dni, to na 4 pozycji ustawiamy ?. Tak samo jeśli chcemy wywoływać usługę każdego 5 dnia miesiąca nie zważając na to jaki to będzie dzień tygodnia, to na 6 pozycji ustawiamy ?.

Poniżej parę przykładów:

  • * 9 12 * * * - co sekundę przez minutę od godz. 12:09:00 każdego dnia
  • 0 0 2-4 * * * - godz.2:00:00, 3:00:00 i 4:00:00 każdego dnia
  • 0 * 6,19 * * 2 - 6:00:00 i 19:00:00 w każdy wtorek
  • 0 0/30 10 * JAN * - 10:00:00, 10:30:00 każdego dnia stycznia
  • 0 0 12 * * MON-FRI - 12:00:00 od poniedziałku do piątku
  • 0 0 0 3 5 ? - każdego 3 maja o północy

2. fixedDelay Czas w milisekundach pomiędzy ostatnio zakończonym zadaniem a rozpoczęciem następnego. Poprzednie zadanie musi być zakończone. 3. fixedDelayString Tak samo jak fixedDelay, ale parametr jest typu String, a nie long. 4. fixedRate Czas w milisekundach pomiędzy wywołaniami zadań. Poprzednie zadanie nie musi być zakończone. 5. fixedRateString Tak samo jak fixedRate, ale parametr jest typu String, a nie long. 6. initialDelay Opóźnienie w milisekundach przed wykonaniem pierwszego zadania fixedRate() lub fixedDelay(). 7. initialDelayString Tak samo jak initialDelay, ale parametr jest typu String, a nie long. 8. zone Strefa czasowa, dla której zadanie będzie wykonywane.

Zmiana parametru @Scheduled w trybie runtime:

Wartość parametru adnotacji @Scheduled można ustawić w trakcie działania programu. Można wykorzystać do tego metodę configureTasks z interfejsu SchedulingConfigurer. Przyjmuje ona w parametrze obiekt klasy ScheduledTaskRegistrar, na którym możemy wywołać metody pozwalające nam zmienić interesujący nas parametr. Do powyższego przykładu dodałam klasę konfiguracyjną, w której po 20 sekundach od uruchomienia programu wartość fixedRate zmienia się z 5 sekund na 1. Zamiast wykorzystanej przeze mnie metody addFixedRateTask możemy użyć addFixedDelayTask lub addTriggerTask. Więcej szczegółów TUTAJ.

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {

@Bean
public ScheduledTask scheduledTask() {
    return new ScheduledTask();
}

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    final LocalDateTime dateChange = LocalDateTime.now().plusSeconds(20);
        taskRegistrar.addFixedRateTask(new Runnable() {
            @Override
            public void run() {
                if(LocalDateTime.now().isAfter(dateChange)) {
                    scheduledTask().executeTask();
                }
            }
        }, 1000);
}

}

Wynik działania zmodyfikowanego programu poniżej. Przez 20 pierwszych sekund (14:55:46-14:56:06) task uruchamiany jest co 5 sekund, a później co 1 sekundę.

SchedulingRuntime Cały projekt można znaleźć TUTAJ. Scheduling wykorzystać możemy przy cyklicznym wysyłaniu maili (np. przy wysyłaniu ofert). Jeżeli chcecie się dowiedzieć czegoś więcej zapraszam TUTAJ.

Zachęcam również do obejrzenia video:

https://www.youtube.com/watch?v=TEMsEcdAsbY