Comment exécuter une tâche de fond dans une application web basée sur servlet?

j'utilise Java et je veux garder un servlet en fonctionnement continu dans mon application, mais je ne sais pas comment le faire. Ma servlet est une méthode qui donne de compte de l'utilisateur à partir d'une base de données sur une base quotidienne ainsi que le nombre total des utilisateurs de la base de données entière. Je veux donc que le servlet continue de fonctionner pour cela.

78
demandé sur BalusC 2011-01-14 15:39:45

5 réponses

votre problème est que vous ne comprenez pas le but du servlet . Il est prévu d'agir sur les requêtes HTTP, rien de plus. Vous voulez juste une tâche de fond qui fonctionne une fois sur une base quotidienne.

EJB disponible? Use @Schedule

si votre environnement supporte EJB (par exemple WildFly, JBoss AS/EAP, TomEE, GlassFish, etc.), utilisez @Schedule à la place.

@Singleton
public class BackgroundJobManager {

    @Schedule(hour="0", minute="0", second="0", persistent=false)
    public void someDailyJob() {
        // Do your job here which should run every start of day.
    }

    @Schedule(hour="*/1", minute="0", second="0", persistent=false)
    public void someHourlyJob() {
        // Do your job here which should run every hour of day.
    }

    @Schedule(hour="*", minute="*/15", second="0", persistent=false)
    public void someQuarterlyJob() {
        // Do your job here which should run every 15 minute of hour.
    }

} 

Oui, c'est tout. Le conteneur sera automatiquement ramassage et de les gérer.

EJB indisponible? Use ScheduledExecutorService

si votre environnement ne supporte pas EJB (c.-à-d. pas un vrai serveur Java EE, par exemple Tomcat, Jetty, etc), Utilisez ScheduledExecutorService . Ceci peut être initié par un ServletContextListener . Voici un exemple de coup d'envoi:

@WebListener
public class BackgroundJobManager implements ServletContextListener {

    private ScheduledExecutorService scheduler;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
        scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
        scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        scheduler.shutdownNow();
    }

}

où le les classes d'emploi ressemblent à ceci:

public class SomeDailyJob implements Runnable {

    @Override
    public void run() {
        // Do your daily job here.
    }

}
public class SomeHourlyJob implements Runnable {

    @Override
    public void run() {
        // Do your hourly job here.
    }

}
public class SomeQuarterlyJob implements Runnable {

    @Override
    public void run() {
        // Do your quarterly job here.
    }

}

Ne jamais penser à utiliser java.util.Timer / java.lang.Thread Java EE

N'utilisez jamais directement java.util.Timer et/ou java.lang.Thread en Java EE. C'est la recette pour l'ennui. Une explication détaillée peut être trouvée dans cette réponse relative au JSF sur la même question: fils de frai dans un JSF géré bean pour les tâches programmées en utilisant un minuteur .

178
répondu BalusC 2017-05-23 12:10:08

je suggère d'utiliser une bibliothèque comme quartz afin d'exécuter la tâche à intervalles réguliers. Qu'est-ce que le servlet fait vraiment ? Il vous envoie un rapport ?

4
répondu Twister 2011-01-14 13:08:04
2
répondu Rookie 2011-12-22 08:13:51

implémenter deux classes et appeler startTask() dans main .

public void startTask()
{
    // Create a Runnable
    Runnable task = new Runnable() {
        public void run() {
            while (true) {
                runTask();
            }
        }
    };

    // Run the task in a background thread
    Thread backgroundThread = new Thread(task);
    // Terminate the running thread if the application exits
    backgroundThread.setDaemon(true);
    // Start the thread
    backgroundThread.start();
}

public void runTask()
{
    try {
        // do something...         
        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
2
répondu Ali Alimohammadi 2018-03-05 18:10:30

dans un système de production qui peut comporter plusieurs conteneurs non jee. Utilisez anot enterprise scheduler comme Quartz scheduler qui peut être configuré pour utiliser une base de données pour tâche maamgememt.

0
répondu Jeryl Cook 2016-02-21 15:31:16