Frage Wie führe ich eine Hintergrundaufgabe in einer Servlet-basierten Webanwendung aus?


Ich benutze Java und möchte ein Servlet in meiner Anwendung laufen lassen, aber ich verstehe nicht, wie es geht. Mein Servlet verfügt über eine Methode, die täglich die Anzahl der Benutzer aus einer Datenbank sowie die Gesamtzahl der Benutzer aus der gesamten Datenbank angibt. Also möchte ich das Servlet kontinuierlich laufen lassen.


76
2018-01-14 12:39


Ursprung


Antworten:


Ihr Problem ist, dass Sie den Zweck der. Falsch verstehen Servlet. Es ist beabsichtigt, auf HTTP-Anfragen zu reagieren, mehr nicht. Sie möchten nur eine Hintergrundaufgabe, die einmal täglich ausgeführt wird.

EJB verfügbar? Benutzen @Schedule

Wenn Ihre Umgebung EJB unterstützt (z. B. WildFly, JBoss AS / EAP, TomEE, GlassFish usw.), dann verwenden Sie @Schedule stattdessen.

@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.
    }

} 

Ja, das ist wirklich alles. Der Container wird automatisch übernommen und verwaltet.

EJB nicht verfügbar? Benutzen ScheduledExecutorService

Wenn Ihre Umgebung EJB nicht unterstützt (d. H. Kein echter Java EE-Server, z. B. Tomcat, Jetty usw.), verwenden Sie ScheduledExecutorService. Dies kann durch a eingeleitet werden ServletContextListener. Hier ist ein Kickoff-Beispiel:

@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();
    }

}

Wo die Job-Klassen so aussehen:

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.
    }

}

Denken Sie niemals über die Verwendung nach java.util.Timer/java.lang.Thread in Java EE

Niemals direkt benutzen java.util.Timer und / oder java.lang.Thread in Java EE. Dies ist ein Rezept für Ärger. Eine ausführliche Erklärung kann in dieser JSF-bezogenen Antwort zu derselben Frage gefunden werden: Erstellen von Threads in einer JSF-verwalteten Bean für geplante Tasks mithilfe eines Timers.


173
2018-01-14 13:45



Ich würde vorschlagen, eine Bibliothek wie Quarz zu verwenden, um die Aufgabe in regelmäßigen Abständen auszuführen. Was macht das Servlet wirklich? Es sendet Ihnen einen Bericht?


3
2018-01-14 13:08



Sie können cron4j verwenden. http://www.sauronsoftware.it/projects/cron4j/manual.php


1
2017-12-22 08:13



Implementieren Sie zwei Klassen und rufen Sie an startTask() im 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();
    }
}

1
2018-03-05 17:49



In einem Produktionssystem, in dem möglicherweise mehrere Nicht-Jee-Container ausgeführt werden. Verwenden Sie einen Enterprise-Scheduler wie den Quartz-Scheduler, der so konfiguriert werden kann, dass er eine Datenbank für den Task maamgememt verwendet.


0
2018-02-21 15:31