2010-02-12 5 views
19

Ho sviluppato un'applicazione Web utilizzando servlet e JSP. Non sto usando alcun framework di per sé, usando invece il mio framework MVC fatto in casa. Sto usando MySQL come back-end.esecuzione di attività periodica sul lato server per servlet JSP Sito Web MVC

voglio fare quanto segue:

  1. Clean up alcuni dati dalla base di dati ogni ora
  2. Generare e statistiche memorizzare circa i dati ogni 15 minuti in un file XML da qualche parte

Il problema è: attualmente tutto il mio codice viene eseguito come risultato della richiesta ricevuta da un client.

Come si eseguono attività periodiche sul lato server?

Una soluzione che ho ora è quella di creare un thread nella funzione init del controller. Ci sono altre opzioni?

risposta

41

È possibile utilizzare ServletContextListener per eseguire l'inizializzazione all'avvio di Webapp. Il modo standard dell'API Java per eseguire attività periodiche sarebbe una combinazione di Timer e TimerTask. Ecco un esempio di kickoff:

public void contextInitialized(ServletContextEvent event) { 
    Timer timer = new Timer(true); 
    timer.scheduleAtFixedRate(new CleanDBTask(), 0, oneHourInMillis); 
    timer.scheduleAtFixedRate(new StatisticsTask(), 0, oneQuartInMillis); 
} 

in cui i compiti entrambi possono apparire come:

public class CleanDBTask extends TimerTask { 
    public void run() { 
     // Implement. 
    } 
} 

Utilizzando Timer non è consigliabile in Java EE. Se l'attività genera un'eccezione, l'intero thread Timer viene ucciso e in genere è necessario riavviare l'intero server per farlo funzionare di nuovo. Lo Timer è anche sensibile alle modifiche dell'orologio di sistema.

Il modo più nuovo e più robusto java.util.concurrent sarebbe una combinazione di ScheduledExecutorService e solo un Runnable. Ecco un esempio kickoff:

private ScheduledExecutorService scheduler; 

public void contextInitialized(ServletContextEvent event) { 
    scheduler = Executors.newSingleThreadScheduledExecutor(); 
    scheduler.scheduleAtFixedRate(new CleanDBTask(), 0, 1, TimeUnit.HOURS); 
    scheduler.scheduleAtFixedRate(new StatisticsTask(), 0, 15, TimeUnit.MINUTES); 
} 

public void contextDestroyed(ServletContextEvent event) { 
    scheduler.shutdownNow(); 
} 
+2

Basta desidera aggiungere alla risposta fantastica di BalusC che '' metodi scheduleWithFixedDelay' scheduleAtFixedRate' e 'di ScheduledExecutorService' potranno sopprimere le esecuzioni future se è stato rilevato un'eccezione in una corsa. Quindi ricorda di gestire le tue eccezioni. 'Se una qualsiasi esecuzione dell'attività riscontra un'eccezione, le esecuzioni successive vengono soppresse. – dvd