Fale com a gente no WhatsApp Fale com a gente no WhatsApp
Como posso te ajudar?
Milena - Atendimento TreinaWeb

Oi, eu sou a Milena e estou online agora para tirar todas as suas dĂşvidas!

Fechar Fechar
Desenvolvimento Back-end Java

Trabalhando com Scheduled Tasks no Spring Boot

Descubra o poder das Scheduled Tasks no Spring Boot. Aprenda a criar, configurar e aprimorar tarefas agendadas em Java com o Spring Framework.

2 anos atrás

Formação Desenvolvedor Java
Conheça a formação em detalhes

No vasto ecossistema do desenvolvimento Java, a estrutura do Spring Framework destaca-se como uma escolha primordial para a construção de aplicativos robustos e escaláveis. Dentro desse universo dinâmico, a gestão eficaz de tarefas agendadas desempenha um papel crucial na otimização do desempenho e na automação de processos essenciais. Neste contexto, o Spring Framework oferece um conjunto poderoso de ferramentas para lidar com essas tarefas programadas, por isso, veremos sobre as Scheduled Tasks no Spring Boot.

Criando o projeto

Para exemplificar o uso de Scheduled Tasks no Spring Boot nĂłs precisamos criar um projeto Spring Boot, para isso vamos utilizar o Spring Initializr.

Print da págia do Spring Initializr com as informações para criar o projeto Spring a ser utilizado como exemplo no artigo.

Vamos criar um projeto com as configurações demonstradas acima. Utilizaremos o Maven como gerenciador de projeto, como linguagem usaremos o Java na versão 21, como método de empacotamento iremos utilizar o JAR e teremos como dependência apenas o Spring Web. Além disso, foi definido os seguintes metadados para o projeto:

  • GroupId: br.com.treinaweb
  • ArtifactId: scheduled-tasks
  • Package Name: br.com.treinaweb.scheduledtasks

Agora, basta clicar no botão “Generate” para baixar o projeto base e então abri-lo em um editor de código-fonte ou IDE.

Spring Framework - Fundamentos
Curso Spring Framework - Fundamentos
Conhecer o curso

Configurando o projeto

Para podermos utilizar Scheduled Tasks no Spring Boot, nós precisamos habilitar esse recurso em nossa aplicação. Para isso, nós utilizamos a anotação @EnableScheduling, vamos criar uma classe chamada SchedulingConfig com o seguinte conteúdo:

package br.com.treinaweb.scheduledtasks;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class SchedulingConfig {
    
}

A classe SchedulingConfig possui as seguintes anotações:

  • @Configuration: indica que a classe Ă© uma classe de configuração Spring. No contexto do Spring Framework, as classes de configuração sĂŁo usadas para definir configurações especĂ­ficas da aplicação.
  • @EnableScheduling: ativa o suporte a tarefas agendadas no contexto do Spring. Essa anotação permite que o Spring agende mĂ©todos para serem executados em intervalos especĂ­ficos.

Criando tasks

Agora que nosso projeto está com o recurso de Scheduled Tasks habilitado nós podemos criar as nossas tarefas agendadas, para isso basta criar um método com a lógica da tarefa a se realizada e então anotar esse método com a anotação @Scheduled. Essa anotação recebe alguns parâmetros que irão controlar quando a tarefa em questão será executada.

Spring Framework - Spring Data JPA
Curso Spring Framework - Spring Data JPA
Conhecer o curso

Scheduled Tasks com Fixed Delay

Um dos parâmetros que podemos passar para a anotação Scheduled é o fixedDelay, esse parâmetro nós podemos passar um número que irá representar quanto tempo após a última execução da tarefa é que será realizada a próxima execução, lembrando que esse tempo deve ser passado em milissegundos. Vejamos o exemplo abaixo:

package br.com.treinaweb.scheduledtasks;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SchedulingConfig {

    private static final long FIXED_DELAY = 5 * 1000; // 5 segundos
    
    private final Logger logger = LoggerFactory.getLogger(SchedulingConfig.class);

    @Scheduled(fixedDelay = FIXED_DELAY)
    public void cancelOrderWithoutPayment() {
        // LĂłgica para cancelar pedidos sem pagamento
        logger.info("Executando tarefa agendada para cancelar pedidos sem pagamento");
    }
    
}

No exemplo acima foi criada um método chamado cancelOrderWithoutPayment que irá simular uma tarefa de cancelar pedidos sem pagamento dentro do nosso sistema, esse método não receber nenhum parâmetro e também não irá retornar nada. Além disso, o método foi anotado com a anotação @Scheduled e foi passado o parâmetro fixedDelay com o valor 5000, o que fará com que a tarefa seja executada cinco segundos após a última execução.

Ao executarmos o projeto teremos a seguinte saĂ­da no terminal:

...
2023-11-15T13:55:44.091-03:00  INFO 86405 --- [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-15T13:55:44.126-03:00  INFO 86405 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-15T13:55:44.127-03:00  INFO 86405 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 621 ms
2023-11-15T13:55:44.335-03:00  INFO 86405 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-11-15T13:55:44.351-03:00  INFO 86405 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-11-15T13:55:44.358-03:00  INFO 86405 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T13:55:44.358-03:00  INFO 86405 --- [  restartedMain] b.c.t.s.ScheduledTasksApplication        : Started ScheduledTasksApplication in 1.121 seconds (process running for 1.358)
2023-11-15T13:55:49.358-03:00  INFO 86405 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T13:55:54.358-03:00  INFO 86405 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T13:55:59.359-03:00  INFO 86405 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento

Scheduled Tasks com Fixed Rate

Nós também podemos utilizar o parâmetro fixedRate, diferente do fixedDelay esse parâmetro não leva em consideração a última execução, ou seja, se definirmos um fixedRate de cinco segundos para a nossa tarefa e a mesma demorar três segundo para executar, a próxima execução será em apenas dois segundos, pois o tempo de execução anterior não é levado em consideração.

package br.com.treinaweb.scheduledtasks;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SchedulingConfig {

    private static final long FIXED_RATE = 5 * 1000; // 5 segundos
    
    private final Logger logger = LoggerFactory.getLogger(SchedulingConfig.class);

    @Scheduled(fixedRate = FIXED_RATE)
    public void cancelOrderWithoutPayment() {
        // LĂłgica para cancelar pedidos sem pagamento
        logger.info("Executando tarefa agendada para cancelar pedidos sem pagamento");
    }
    
}

Ao executarmos o projeto teremos uma saĂ­da bem semelhante a anterior, pois a nossa tarefa Ă© bem simples e nĂŁo demora quase nada para ser executada.

...
2023-11-15T14:06:49.722-03:00  INFO 91996 --- [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-15T14:06:49.796-03:00  INFO 91996 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-15T14:06:49.798-03:00  INFO 91996 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1010 ms
2023-11-15T14:06:50.248-03:00  INFO 91996 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-11-15T14:06:50.265-03:00  INFO 91996 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-11-15T14:06:50.271-03:00  INFO 91996 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:06:50.272-03:00  INFO 91996 --- [  restartedMain] b.c.t.s.ScheduledTasksApplication        : Started ScheduledTasksApplication in 1.739 seconds (process running for 1.957)
2023-11-15T14:06:55.271-03:00  INFO 91996 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:07:00.271-03:00  INFO 91996 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:07:05.271-03:00  INFO 91996 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento

Spring Framework - Desenvolvimento de APIs REST
Curso Spring Framework - Desenvolvimento de APIs REST
Conhecer o curso

Scheduled Tasks com Cron Expressions

Também é possível configurarmos a execução de nossas tarefas utilizando Cron Expressions, o que nos dar uma maior flexibilidade que não seria possível de alcançar utilizando fixed delay e fixed rate.

Mas primeiramente precisamos entender o que Ă© uma cron expression.

O que Ă© uma Cron Expression?

Uma cron expression é uma string de texto utilizada para representar um conjunto de instruções de agendamento de tempo em sistemas operacionais Unix-like. Essa expressão é comumente usada para agendar a execução de tarefas automatizadas, como scripts, backups ou outras atividades recorrentes.

A expressão cron é composta por cinco campos separados por espaços em branco, representando diferentes aspectos do agendamento. Porém, o Spring utiliza uma versão própria da cron expression padrão do Unix, na versão do Spring nós temos seis campos ao invés de cinco e esses campos funcionam da seguinte forma:

┌───────────── segundo (0-59)
│ ┌───────────── minuto (0 - 59)
│ │ ┌───────────── hora (0 - 23)
│ │ │ ┌───────────── dia do mês (1 - 31)
│ │ │ │ ┌───────────── mês (1 - 12) (or JAN-DEC)
│ │ │ │ │ ┌───────────── dia da semana (0 - 7) (0 or 7 is Sunday, or MON-SUN)
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *

As seguintes regras se aplicam:

  • Um campo pode ser um asterisco (*), que sempre representa “primeiro-Ăşltimo”. Para os campos “dia do mĂŞs” ou “dia da semana”, um ponto de interrogação (?) pode ser usado em vez de um asterisco.
  • Intervalos de nĂşmeros sĂŁo expressos por dois nĂşmeros separados por um hĂ­fen (-). O intervalo especificado Ă© inclusivo. ApĂłs um intervalo (ou *) com /n, especifica o intervalo do valor do nĂşmero atravĂ©s do intervalo.
  • Nomes em inglĂŞs tambĂ©m podem ser usados nos campos “mĂŞs” e “dia da semana”. Use as trĂŞs primeiras letras do dia ou mĂŞs especĂ­fico (maiĂşsculas ou minĂşsculas nĂŁo importam).
  • Os campos “dia do mĂŞs” e “dia da semana” podem conter um caractere L, que representa “último” e tem um significado diferente em cada campo:
    • No campo “dia do mĂŞs”, L representa “o Ăşltimo dia do mĂŞs”. Se seguido por um deslocamento negativo (ou seja, L-n), significa “n-Ă©simo Ăşltimo dia do mĂŞs”. Se seguido por W (ou seja, LW), significa “o Ăşltimo dia Ăştil do mĂŞs”.
    • No campo “dia da semana”, dL ou DDDL significa “o Ăşltimo dia da semana d (ou DDD) no mĂŞs”.
  • O campo “dia do mĂŞs” pode ser nW, que representa “o dia Ăştil mais prĂłximo ao dia do mĂŞs n”. Se n cair em um sábado, isso resulta na sexta-feira anterior. Se n cair em um domingo, isso resulta na segunda-feira seguinte, o que tambĂ©m acontece se n for 1 e cair em um sábado (ou seja, 1W significa “o primeiro dia Ăştil do mĂŞs”).
  • O campo “dia da semana” pode ser d#n (ou DDD#n), que representa “o n-Ă©simo dia da semana d (ou DDD) no mĂŞs”.

Alguns exemplos de expressões:

  • “0 0 * * * “: o inĂ­cio de cada hora todos os dias.
  • “/10 * * * * *”: a cada dez segundos.
  • “0 0 8-10 * * *”: 8, 9 e 10 horas todos os dias.
  • “0 0 6,19 * * *”: 6:00 e 19:00 todos os dias.
  • “0 0/30 8-10 * * *”: 8:00, 8:30, 9:00, 9:30, 10:00 e 10:30 todos os dias.
  • “0 0 9-17 * * MON-FRI”: a cada hora, das nove Ă s cinco, nos dias Ăşteis.
  • “0 0 0 25 12 ?”: todo Dia de Natal Ă  meia-noite.
  • “0 0 0 L * *”: Ăşltimo dia do mĂŞs Ă  meia-noite.
  • “0 0 0 L-3 * *”: terceiro dia Ăştil do mĂŞs Ă  meia-noite.
  • “0 0 0 1W * *”: primeiro dia Ăştil do mĂŞs Ă  meia-noite.
  • “0 0 0 LW * *”: Ăşltimo dia Ăştil do mĂŞs Ă  meia-noite.
  • “0 0 0 * * 5L”: Ăşltimo sexta-feira do mĂŞs Ă  meia-noite.
  • “0 0 0 * * THUL”: Ăşltima quinta-feira do mĂŞs Ă  meia-noite.
  • “0 0 0 ? * 5#2”: a segunda sexta-feira do mĂŞs Ă  meia-noite.
  • “0 0 0 ? * MON#1”: a primeira segunda-feira do mĂŞs Ă  meia-noite.

Utilizando Cron Expresisons

Agora que já sabemos o que é uma cron expression e como elas se comportam, vamos ver um exemplo de sua utilização com as Scheduled Tasks no Spring Boot:

package br.com.treinaweb.scheduledtasks;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SchedulingConfig {

    private static final String EVERY_FIVE_SECONDS = "*/5 * * * * *";
    
    private final Logger logger = LoggerFactory.getLogger(SchedulingConfig.class);

    @Scheduled(cron = EVERY_FIVE_SECONDS)
    public void cancelOrderWithoutPayment() {
        // LĂłgica para cancelar pedidos sem pagamento
        logger.info("Executando tarefa agendada para cancelar pedidos sem pagamento");
    }
    
}

Para utilizarmos uma cron expression, nós continuamos usando a anotação @Scheduled, mas agora passamos o paramétrio cron, nesse exemplo utilizamos a cron expression "*/5 * * * * *", que significa que a tarefa será executada a cada cinco segundos.

Ao executar o projeto veremos o seguinte log no terminal:

2023-11-15T14:48:50.715-03:00  INFO 111858 --- [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-15T14:48:50.750-03:00  INFO 111858 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-15T14:48:50.751-03:00  INFO 111858 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 599 ms
2023-11-15T14:48:50.948-03:00  INFO 111858 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-11-15T14:48:50.963-03:00  INFO 111858 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-11-15T14:48:50.970-03:00  INFO 111858 --- [  restartedMain] b.c.t.s.ScheduledTasksApplication        : Started ScheduledTasksApplication in 1.114 seconds (process running for 1.355)
2023-11-15T14:48:55.001-03:00  INFO 111858 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:49:00.000-03:00  INFO 111858 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:49:05.000-03:00  INFO 111858 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento
2023-11-15T14:49:10.000-03:00  INFO 111858 --- [   scheduling-1] b.c.t.scheduledtasks.SchedulingConfig    : Executando tarefa agendada para cancelar pedidos sem pagamento

ConclusĂŁo

Em conclusão, exploramos a poderosa capacidade do Spring Framework para lidar com tarefas agendadas por meio do módulo de Scheduled Tasks no Spring Boot. Ao longo do artigo, criamos um projeto Spring Boot, configuramos as tarefas agendadas usando anotações como @EnableScheduling e @Scheduled, e exploramos diferentes estratégias de agendamento, como fixedDelay, fixedRate, e até mesmo Cron Expressions.

A gestão eficiente de tarefas agendadas é essencial para a automação de processos e otimização de desempenho em aplicações Java. O Spring Framework, com sua abordagem simples e flexível, oferece uma solução robusta para atender a essas necessidades. Ao empregar as técnicas apresentadas neste artigo, os desenvolvedores podem criar sistemas mais eficientes e automatizados, garantindo a execução de tarefas no momento adequado e melhorando a experiência geral do usuário.

Autor(a) do artigo

Cleyson Lima
Cleyson Lima

Professor, programador, fã de One Piece e finge saber cozinhar. Cleyson é graduando em Licenciatura em Informática pelo IFPI - Campus Teresina Zona Sul, nos anos de 2019 e 2020 esteve envolvido em vários projetos coordenados pela secretaria municipal de educação da cidade de Teresina, onde o foco era introduzir alunos da rede pública no mundo da programação e robótica. Hoje é instrutor dos cursos de Spring na TreinaWeb, mas diz que seu coração sempre pertencerá ao Python.

Todos os artigos

Artigos relacionados Ver todos