Статьи Утилиты Telegram YouTube Отзывы

Запуск задач по расписанию в Spring Boot

3 мая 2018

Тэги: Java, maven, Spring, Spring Boot.

Часто в приложениях возникает необходимость выполнять некоторые действия по расписанию, а не по запросу извне. Первое, что приходит на ум – это планировщик cron. Но если вы пишете приложение, используя Spring Boot, то можете реализовать похожий функционал, добавив всего пару аннотаций.

В качестве примера давайте создадим простой maven-проект. Затем пропишем в pom-файле Spring Boot как родителя для данного проекта:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.12.RELEASE</version>
</parent>

Также у вас должна быть секция build со стандартным содержимым:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Теперь добавим стандартный main-класс:

@EnableScheduling
@SpringBootApplication(scanBasePackages = "ru.devmark")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Аннотация @SpringBootApplication говорит о том, что это Spring Boot приложение. Параметр scanBasePackages указывает, какие пакеты (включая вложенные пакеты) сканировать для создания бинов средствами Spring.

Аннотация @EnableScheduling разрешает выполнение задач по расписанию для данного приложения. Если этой аннотации не будет, наш планировщик работать не будет.

Теперь создадим целевой сервис, в котором будет метод, выполняющий некоторую бизнес-логику. В нашем случае эту логику будем имитировать обычной задержкой через TimeUnit.SECONDS.sleep().

@Service
public class SchedulerService {

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

    @Scheduled(initialDelayString = "3000", fixedDelayString = "3000")
    public void doWork() throws InterruptedException {
        log.info("Start process");
        TimeUnit.SECONDS.sleep(5);
        log.info("End process");
    }
}

Аннотация @Scheduled вешается на любой метод, который нужно выполнять по фиксированному расписанию.

Параметр initialDelayString задаёт время в миллисекундах, которое пройдёт перед первым запуском данной задачи. Данный параметр бывает полезным, если после старта вашему приложению требуется время для дополнительной инициализации.

Параметр fixedDelayString задаёт время в миллисекундах между запусками данной задачи.

В нашем примере произойдёт первичная задержка в 3 секунды, затем метод будет работать 5 секунд, затем будет пауза в 3 секунды, затем будет второй запуск длиной в 5 секунд и т.д. Все задачи данного метода будут выполняться последовательно, в один поток. При этом методов с аннотацией @Scheduled может быть сколько угодно и каждый их них будет работать в своём потоке. Spring полностью берёт на себя управление этими потоками, поэтому вам больше ничего указывать не нужно.

Чтобы не хардкодить значения задержек в исходниках, а менять их через файл настроек application.properties (в командной строке путь до него задаётся через параметр --spring.config.location), можно добавить в этот файл новый параметр:

scheduler.delay=3000

Тогда аннотация @Scheduled для нашего примера примет такой вид:

@Scheduled(initialDelayString = "${scheduler.delay}", fixedDelayString = "${scheduler.delay}")

Здесь мы пользуемся другой фичой Spring, которая позволяет динамически подставлять значения параметров по их имени.


Облако тэгов

Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.

Последние статьи


Комментарии

24.05.2022 20:59 Александр

Подскажите актуальный способ отключения планировщика и возобновления задания по требованию.

24.05.2022 23:35 devmark

Наиболее простое решение - это хранить специальный признак в базе (можно отдельную таблицу завести), который считывать при каждом срабатывании аннотации Scheduled и проверять это значение. Если значение флага равно false, то просто ничего не делать. То есть в выключенном состоянии шедулер будет работать вхолостую.

Добавить комментарий

×

devmark.ru