Cómo ejecutar una tarea de fondo en una aplicación web basada servlet?
Pregunta
Estoy usando Java y quiero seguir un servlet continua funcionando en mi solicitud, pero ahora no recibo cómo hacerlo. Mi servlet tiene un método que da cuentas de usuario desde una base de datos sobre una base diaria, así como el recuento total de los usuarios de toda la base de datos. Así que quiero mantener el servlet continuamente corriendo por ello.
Solución
Su problema es que usted no entiende el propósito de la servlet . Se intented a actuar sobre las peticiones HTTP, nada más. Sólo desea una tarea en segundo plano que se ejecuta una vez en base diaria.
EJB disponibles? Utilice @Schedule
Si el entorno de pasar a EJB apoyo (es decir, un verdadero servidor Java EE como JBoss, JBoss, TomEE, Payara, GlassFish, etc), a continuación, utilizar @Schedule
lugar. He aquí algunos ejemplos:
@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.
}
}
Sí, eso es todo. El contenedor será automáticamente recogida y administrarla.
EJB disponible? Utilice ScheduledExecutorService
Si su entorno EJB no apoyo (es decir, no va a usar no es un verdadero servidor Java EE, pero un barebones servletcontainer como Tomcat, Espolón, etc), a continuación, utilizar ScheduledExecutorService
. Esto puede ser iniciado por un ServletContextListener
. He aquí un ejemplo patada de salida:
@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();
}
}
Cuando las clases de trabajo se ven así:
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.
}
}
No vuelvas a pensar en usar java.util.Timer
/ java.lang.Thread
en un entorno basado en Java EE / servlet
Por último, pero no menos importante, no utilizar directamente java.util.Timer
y / o java.lang.Thread
en Java EE. Esta es la receta para los problemas. Una explicación elaborada se puede encontrar en esta respuesta JSF-relacionado en la misma pregunta: el desove hilos en un bean gestionado JSF para las tareas programadas usando un temporizador .
Otros consejos
Se recomienda usar una biblioteca como el cuarzo con el fin de ejecutar la tarea a intervalos regulares. ¿Qué hace el servlet realmente? Se le enviará un informe?
Implementar dos clases y startTask()
llamada en 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();
}
}
Puede utilizar cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
En un sistema de producción que puede tener múltiples envases no Jee en ejecución. Utilice anot programador de la empresa como el cuarzo planificador que puede ser configurado para utilizar una base de datos para maamgememt tarea.