Frage

Ich bin mit Java und ich möchte ein Servlet halten ständig in meiner Anwendung ausgeführt wird, aber ich bin nicht immer, wie es geht. Mein Servlet hat eine Methode, die Zählungen des Benutzers aus einer Datenbank auf einer täglichen Basis, sowie die Gesamtzahl der Nutzer aus der gesamten Datenbank gibt. Also habe ich das Servlet kontinuierlich laufen für das halten wollen.

War es hilfreich?

Lösung

Ihr Problem ist, dass Sie mißverstehen der Zweck des Servlet . Es ist zu handeln intented auf HTTP-Anfragen, nichts weiter. Sie wollen einfach nur eine Hintergrundaufgabe, die auf täglicher Basis einmal ausgeführt wird.

EJB zur Verfügung? Verwenden Sie @Schedule

Wenn Sie Ihre Umgebung zu unterstützen EJB geschehen (dh eine echte Java EE-Server wie Wildfly, JBoss, TomEE, Payara, Glassfish, etc), dann verwenden Sie @Schedule statt. Hier sind einige Beispiele:

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

    @Schedule(hour="*", minute="*", second="*/5", persistent=false)
    public void someFiveSecondelyJob() {
        // Do your job here which should run every 5 seconds.
    }

} 

Ja, das ist wirklich alles. Der Container wird automatisch Pick-up und verwaltet sie.

EJB nicht verfügbar? Verwenden Sie ScheduledExecutorService

Wenn Ihre Umgebung nicht unterstützt EJB (dh Sie nicht keine echten Java EE-Server verwenden, aber ein Barebone servletcontainer wie Tomcat, Jetty, etc), dann verwenden Sie ScheduledExecutorService . Dies kann durch eine eingeleitet werden ServletContextListener . Hier ist ein Kick-off-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);
        scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
    }

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

}

Wenn die Job-Klassen wie folgt 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.
    }

}
public class SomeFiveSecondelyJob implements Runnable {

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

}

Denken Sie nicht immer über die Verwendung von java.util.Timer / java.lang.Thread in einer Java EE / Servlet-basierten Umgebung

Last but not least, nie direkt verwenden java.util.Timer und / oder java.lang.Thread in Java EE. Dies ist Rezept für Ärger. Eine aufwendige Erklärung kann in diesem JSF-bezogene Antwort auf die gleiche Frage zu finden: Laichen Threads in einer JSF Managed Bean für geplante Tasks eines Timer verwendet wird.

Andere Tipps

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

Implementieren Sie zwei Klassen und Call startTask() in 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();
    }
}

In einem Produktionssystem, die mehr nicht-jee Behälter laufen kann. Verwenden Sie Anot Enterprise Scheduler wie Quartz Scheduler, die so konfiguriert werden kann, eine Datenbank für die Aufgabe maamgememt zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top