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.
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 .
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 ?
vous pouvez utiliser cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
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();
}
}
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.