Exécutation de tâches planifiées en arrière-plan sur Spring MVC

View more categories:

1- Spring @Scheduled Annotation

Parfois, dans une application, vous devez créer une tâche planifiée à exécuter en arrière-plan. Par exemple, créer un fichier sitemaps, envoyer un email périodiquement, ...
@Scheduled est une annotation utilisée pour configurer un planning (schedule), elle est annotée sur une méthode et cette méthode sera exécutée selon le calendrier configuré par @Scheduled.
@Scheduled
public @interface Scheduled {
 
    String cron() default "";
 
    String zone() default "";
 
    long fixedDelay() default -1;
 
    String fixedDelayString() default "";
 
    long fixedRate() default -1;
 
    String fixedRateString() default "";
 
    long initialDelay() default -1;
 
    String initialDelayString() default "";

}
Attribut Description
cron Une expression de type cron, étendant la définition habituelle de l' UN*X, elle comprend 6 champs "seconde, minute, heure, le jour du mois, le mois et le jour de la semaine". Elle indique un plan compliqué. (Voir plus au document ci-dessous).
  • @return une expression qui peut être analysée dans un plan de cron
zone Un fuseau horaire pour lequel l'expression cron sera résolue. Par défaut, cet attribut est la chaîne vide (c'est-à-dire que le fuseau horaire local du serveur sera utilisé).
fixedDelay Exécutez la méthode annotée (annotated) avec une période fixe en millisecondes entre la fin de la dernière invocation et le début de la prochaine.
  • @return le délai en millisecondes.
fixedDelayString Exécutez la méthode annotée (annotated) avec une période fixe en millisecondes entre la fin de la dernière invocation et le début de la prochaine..
  • @return le délai en millisecondes en tant que valeur de chaîne, par exemple un espace réservé.
fixedRate Exécutez la méthode annotée (annotated) avec une période fixe en millisecondes entre les invocations.
  • @return la période en millisecondes.
fixedRateString Exécutez la méthode annotée (annotated) avec une période fixe en millisecondes entre les invocations.
  • @return  la période en millisecondes en tant que valeur de chaîne, par ex. un espace réservé.
initialDelay Le nombre de millisecondes à retarder avant la première exécution d'une tâche fixedRate() ou fixedDelay().
  • @return le délai initial en millisecondes
initialDelayString Nombre de millisecondes à retarder avant la première exécution d'une tâche fixedRate() ou fixedDelay().
  • @return le délai initial en millisecondes en tant que valeur de chaîne, par ex. un espace réservé.

2- Configurer de Maven & web.xml

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.o7planning</groupId>
  <artifactId>SpringMVCSchedule</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringMVCSchedule Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
   
            <!-- Servlet Library -->
        <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- Spring dependencies -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>

        <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>

        <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
       
  </dependencies>
 
 
    <build>
      <finalName>SpringMVCSchedule</finalName>
      <plugins>
    
          <!-- Config: Maven Tomcat Plugin -->
          <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
          <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
              <!-- Config: contextPath and Port (Default: /SpringMVCSchedule : 8080) -->
              <!--
              <configuration>
                  <path>/</path>
                  <port>8899</port>
              </configuration>
              -->   
          </plugin>
      </plugins>
  </build>    
 
</project>

 
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">

 <display-name>Spring MVC Schedule</display-name>
 
 
   
</web-app>

3- Configurer Spring MVC

ApplicationContextConfig.java
package org.o7planning.springmvcschedule.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("org.o7planning.springmvcschedule.*")
public class ApplicationContextConfig {

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

}
SpringWebAppInitializer.java
package org.o7planning.springmvcschedule.config;


import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}
WebMvcConfig.java
package org.o7planning.springmvcschedule.config;


import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

   private static final Charset UTF8 = Charset.forName("UTF-8");

   // Config UTF-8 Encoding.
   @Override
   public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
       StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
       stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
       converters.add(stringConverter);

       // Add other converters ...
   }

   // Static Resource Config
   // equivalents for <mvc:resources/> tags
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
       registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
       registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
   }

   // Equivalent for <mvc:default-servlet-handler/> tag
   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       configurer.enable();
   }

}
La configuration vous permet d'utiliser un plan (Schedule):
SchedulerConfig.java
package org.o7planning.springmvcschedule.config;

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

@Configuration
@EnableScheduling
public class SchedulerConfig {
 
    // Declaring the beans are related to the schedule here if necessary.
   
}

 

4- fixedDelay & fixedRate

C'est l'exemple le plus simple, utilisant  @Schedule avec l'attribut  fixedDelay. Dans cet exemple, la tâche imprimera l'heure actuelle  Console et lorsque la tâche est terminé, elle arrêtera  fixedDelay le seconde avant qu'elle effectue la tâche à nouveau.
WriteCurrentTimeSchedule.java
package org.o7planning.springmvcschedule.schedule;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class WriteCurrentTimeSchedule {

  private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss sss");


  // 2 second.
  @Scheduled(fixedDelay = 2 * 1000)
  public void writeCurrentTime() {
   
      Date now = new Date();
   
      String nowString = df.format(now);
   
      System.out.println("Now is: "+ nowString);
   
  }

}
Vous pouvez configurer le temps de retard pour la première exécution ( initialDelay), après l'application start, la tâche est effectuée uniquement lorsque le délai est en cours.
// miliseconds.
@Scheduled(fixedDelay = 2 * 1000, initialDelay = 30 * 1000)
public void writeCurrentTime() {
 
   // Do something ..

}

Comparer fixedDelay avec fixedRate

Vous ne pouvez utiliser que fixedDelay ou fixedRate dans l'annotation @Schedule, mais vous ne pouvez pas utiliser les deux simultanément.
  • fixedDelayest la période de repos lorsque la tâche est terminée. Après le temps de repos, il effectuera la prochaine tâche.
  • fixedRate est la période qui se situe entre l'heure de début d'exécution de la tâche précédente et l'heure de début pour effectuer la tâche suivante, elle ne dépend pas si la tâche précédente est terminée ou non.

5- L'expression cron et zone

@Schedule vous permet de configurer des programmes complexes, par exemple, effectuer des tâches toutes les 12 heures lundi. Pour configurer les programmes complexes, vous pouvez utiliser l'attribut cron.
L'expression  cron est représentée par six champs:
second, minute, hour, day of month, month, day(s) of week
Exemple:
"0 0 * * * *" // the top of every hour of every day.

"*/10 * * * * *" // every ten seconds.

"0 0 8-10 * * *" // 8, 9 and 10 o'clock of every day.

"0 0/30 8-10 * * *" // 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.

"0 0 9-17 * * MON-FRI" // on the hour nine-to-seventeen, and monday to friday

"0 0 0 25 12 ?" // every Christmas Day at midnight
Description:
Modèle Signification
* signifie correspondre à quelques
*/X signifie "Tous les X"
? ("Aucune valeur spécifique") - utile lorsque vous devez spécifier quelque chose dans l'un des deux champs dans lesquels le caractère est autorisé, mais pas l'autre. Par exemple, si je veux le 10ème jour dans un mois mais je ne concerne pas il sera quel jour dans la semaine, je dois mettre "10" au champ day-of-month, et mettre "?" au champ day-of-week.

"0 0 0 25 12 ?":

À 12 minuit (0 heure) le jour de Noël (le 25 décembre), ça ne vous dérange pas à quel jour il est.
L'attribut  zone spécifiait le fuseau horaire. La valeur par défaut de zone est vide, ce qui signifie utiliser le fuseau horaire du server.
@Scheduled(cron="0 1 1 * * *", zone="Europe/Istanbul")

public void doScheduledWork() {
    // Do something here
}
Le tableau suivant contient une liste des fuseaux horaires (Time zones) pris en charge par  Oracle Real-Time Collaboration.
Internal Name External User Visible Name
Pacific/Pago_Pago (-11:00) Pago Pago
Pacific/Honolulu (-10:00) Hawaii
America/Anchorage (-09:00) Alaska
America/Vancouver (-08:00) Canada Pacific Time
America/Los_Angeles (-08:00) US Pacific Time
America/Tijuana (-08:00) Tijuana
America/Edmonton (-07:00) Canada Mountain Time
America/Denver (-07:00) US Mountain Time
America/Phoenix (-07:00) Arizona
America/Mazatlan (-07:00) Mazatlan
America/Winnipeg (-06:00) Canada Central Time
America/Regina (-06:00) Saskatchewan
America/Chicago (-06:00) US Central Time
America/Mexico_City (-06:00) Mexico City
America/Guatemala (-06:00) Guatemala
America/El_Salvador (-06:00) El Salvador
America/Managua (-06:00) Managua
America/Costa_Rica (-06:00) Costa Rica
America/Montreal (-05:00) Canada Eastern Time
America/New_York (-05:00) US Eastern Time
America/Indianapolis (-05:00) East Indiana
America/Panama (-05:00) Panama
America/Bogota (-05:00) Bogota
America/Lima (-05:00) Lima
America/Halifax (-04:00) Canada Atlantic Time
America/Puerto_Rico (-04:00) Puerto Rico
America/Caracas (-04:00) Caracas
America/Santiago (-04:00) Santiago
America/St_Johns (-03:30) Newfoundland
America/Sao_Paulo (-03:00) Sao Paulo
Atlantic/Azores (-01:00) Azores
Etc./UTC (00:00) Universal Time
UTC (00:00) Universal Time
Atlantic/Reykjavik (00:00) Reykjavik
Europe/Dublin (00:00) Dublin
Europe/London (00:00) London
Europe/Lisbon (00:00) Lisbon
Africa/Casablanca (00:00) Casablanca
Africa/Nouakchott (00:00) Nouakchott
Europe/Oslo (+01:00) Oslo
Europe/Stockholm (+01:00) Stockholm
Europe/Copenhagen (+01:00) Copenhagen
Europe/Berlin (+01:00) Berlin
Europe/Amsterdam (+01:00) Amsterdam
Europe/Brussels (+01:00) Brussels
Europe/Luxembourg (+01:00) Luxembourg
Europe/Paris (+01:00) Paris
Europe/Zurich (+01:00) Zurich
Europe/Madrid (+01:00) Madrid
Europe/Rome (+01:00) Rome
Africa/Algiers (+01:00) Algiers
Africa/Tunis (+01:00) Tunis
Europe/Warsaw (+01:00) Warsaw
Europe/Prague (+01:00) Prague Bratislava
Europe/Vienna (+01:00) Vienna
Europe/Budapest (+01:00) Budapest
Europe/Sofia (+02:00) Sofia
Europe/Istanbul (+02:00) Istanbul
Europe/Athens (+02:00) Athens
Asia/Nicosia (+02:00) Nicosia
Asia/Beirut (+02:00) Beirut
Asia/Damascus (+02:00) Damascus
Asia/Jerusalem (+02:00) Jerusalem
Asia/Amman (+02:00) Amman
Africa/Tripoli (+02:00) Tripoli
Africa/Cairo (+02:00) Cairo
Africa/Johannesburg (+02:00) Johannesburg
Europe/Moscow (+03:00) Moscow
Asia/Baghdad (+03:00) Baghdad
Asia/Kuwait (+03:00) Kuwait
Asia/Riyadh (+03:00) Riyadh
Asia/Bahrain (+03:00) Bahrain
Asia/Qatar (+03:00) Qatar
Asia/Aden (+03:00) Aden
Africa/Khartoum (+03:00) Khartoum
Africa/Djibouti (+03:00) Djibouti
Africa/Mogadishu (+03:00) Mogadishu
Asia/Dubai (+04:00) Dubai
Asia/Muscat (+04:00) Muscat
Asia/Yekaterinburg (+05:00) Yekaterinburg
Asia/Tashkent (+05:00) Tashkent
Asia/Calcutta (+05:30) India
Asia/Novosibirsk (+06:00) Novosibirsk
Asia/Almaty (+06:00) Almaty
Asia/Dacca (+06:00) Dacca
Asia/Krasnoyarsk (+07:00) Krasnoyarsk
Asia/Bangkok (+07:00) Bangkok
Asia/Saigon (+07:00) Vietnam
Asia/Jakarta (+07:00) Jakarta
Asia/Irkutsk (+08:00) Irkutsk
Asia/Shanghai (+08:00) Beijing, Shanghai
Asia/Hong_Kong (+08:00) Hong Kong
Asia/Taipei (+08:00) Taipei
Asia/Kuala_Lumpur (+08:00) Kuala Lumpur
Asia/Singapore (+08:00) Singapore
Australia/Perth (+08:00) Perth
Asia/Yakutsk (+09:00) Yakutsk
Asia/Seoul (+09:00) Seoul
Asia/Tokyo (+09:00) Tokyo
Australia/Darwin (+09:30) Darwin
Australia/Adelaide (+09:30) Adelaide
Asia/Vladivostok (+10:00) Vladivostok
Australia/Brisbane (+10:00) Brisbane
Australia/Sydney (+10:00) Sydney Canberra
Australia/Hobart (+10:00) Hobart
Asia/Magadan (+11:00) Magadan
Asia/Kamchatka (+12:00) Kamchatka
Pacific/Auckland (+12:00) Auckland
Dans l'exemple ci-dessous, la tâche se déroule à 1h20' lundi, mardi, mercredi et jeudi.
"0 20 1 * * MON-THU"
CronSchedule.java
package org.o7planning.springmvcschedule.schedule;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class CronSchedule {

    @Scheduled(cron = "0 20 1 * * MON-THU")
    public void doSomething() {

        System.out.println("Do some thing");

    }

}

View more categories: