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

Запуск задач по расписанию в 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, которая позволяет динамически подставлять значения параметров по их имени.



Комментарии

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

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

24.05.2022 23:35 devmark

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

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

×

devmark.ru