Domanda

Sto usando Java e voglio mantenere un servlet in esecuzione continua nella mia richiesta, ma non sto ottenendo come farlo. La mia servlet ha un metodo che dà i conteggi degli utenti da un database su una base quotidiana, così come il numero totale degli utenti di tutto il database. Quindi voglio mantenere il servlet in esecuzione continua per questo.

È stato utile?

Soluzione

Il problema è che si fraintendere lo scopo della servlet . E 'intented ad agire per le richieste HTTP, niente di più. Si vuole solo un task in background che viene eseguito una volta su base giornaliera.

EJB disponibili? Utilizzare @Schedule

Se l'ambiente capita di supporto EJB (ad esempio un server Java EE reale come wildfly, JBoss, TomEE, Payara, GlassFish, ecc), quindi utilizzare @Schedule . Ecco alcuni esempi:

@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ì, questo è davvero tutto. Il contenitore viene automaticamente pick-up e gestirlo.

EJB non è disponibile? Utilizzare ScheduledExecutorService

Se l'ambiente non EJB non il supporto (per esempio, si sta utilizzando non è non un vero e proprio server di Java EE, ma un barebone servletcontainer come Tomcat, Jetty, ecc), quindi utilizzare ScheduledExecutorService . Questo può essere avviata da un ServletContextListener . Ecco un esempio kickoff:

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

}

Se le classi di lavoro simile a questa:

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

}

Non bisogna mai pensare di utilizzare java.util.Timer / java.lang.Thread in un ambiente basato su Java EE / Servlet

Ultimo ma non meno importante, non utilizzare direttamente java.util.Timer e / o java.lang.Thread in Java EE. Questa è la ricetta di guai. Una spiegazione elaborata può essere trovato in questa risposta JSF-correlate sulla stessa domanda: Deposizione thread in un bean gestito JSF per attività pianificate usando un timer .

Altri suggerimenti

Io suggerirei di usare una libreria come al quarzo, al fine di eseguire l'operazione a intervalli regolari. Che cosa fa il servlet davvero fare? Esso si invia un rapporto?

Implementare due classi e chiamata 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 un sistema di produzione che può avere molteplici contenitori non jee esecuzione. Utilizzare anot scheduler un'impresa come quarzo di pianificazione che può essere configurato per utilizzare un database per l'attività maamgememt.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top