2009-04-27 17 views
58

No estoy muy familiarizado con Tomcat, en mi opinión, básicamente se abstrae como un servidor cgi que guarda la JVM entre llamadas; sé que puede hacer mucho más que eso.Subproceso de fondo para una aplicación de servlet de Tomcat

estoy buscando una manera de poner en marcha un fondo hilo cuando un servidor Tomcat se inicia, lo que actualizar periódicamente el contexto del servidor (en mi caso particular, esto es un hilo que escucha los latidos del corazón de algunos otros servicios y actualizaciones disponibilidad información, pero uno puede imaginar una variedad de usos para esto).

¿Hay una manera estándar de hacer esto? ¿Tanto el lanzamiento como la actualización/consulta del Contexto?

Cualquier puntero a la documentación relevante y/o ejemplos de código sería muy apreciado.

+0

Vale la pena señalar que generalmente puede iniciar un hilo cuando lo desee si hay un lugar más conveniente para hacerlo que cuando se inicializa el contexto. P.ej. podría estar en el método init de un servlet particular, o cuando se inicia una clase en particular, etc. –

Respuesta

77

Si desea iniciar un hilo cuando se despliega el GUERRA, puede definir un oyente contexto en el web.xml:

<web-app> 
    <listener> 
     <listener-class>com.mypackage.MyServletContextListener</listener-class> 
    </listener> 
</web-app> 

luego implementar esa clase algo como:

public class MyServletContextListener implements ServletContextListener { 

    private MyThreadClass myThread = null; 

    public void contextInitialized(ServletContextEvent sce) { 
     if ((myThread == null) || (!myThread.isAlive())) { 
      myThread = new MyThreadClass(); 
      myThread.start(); 
     } 
    } 

    public void contextDestroyed(ServletContextEvent sce){ 
     try { 
      myThread.doShutdown(); 
      myThread.interrupt(); 
     } catch (Exception ex) { 
     } 
    } 
} 
+0

¡Ah! Gracias, eso es muy sencillo. ¿Estoy en lo correcto al decir que "ServletContext" es lo que necesito modificar para que este subproceso pase información a mi servlet, para que pueda usar los estados que mi oyente de latido recopila? – SquareCog

+1

Sí, me perdí esta parte en mi respuesta. :) El ServletConext está disponible desde ServletContextEvent, que podría pasarse al objeto Thread que podría obtener/establecer atributos disponibles para todos los hilos. –

+0

En ese momento, ¿cómo es posible acceder al 'MyServletContextListener' para consultar el hilo? –

12

Estoy buscando una manera de iniciar una cadena de fondo cuando se inicia un servidor Tomcat

Creo que está buscando una forma de iniciar un hilo de fondo cuando su aplicación web es iniciada por Tomcat.

Esto se puede hacer utilizando un ServletContextListener. Está registrado en web.xml y se ejecutará cuando se inicie o se detenga su aplicación. A continuación, puede crear (y luego detener) su subproceso, utilizando las formas Java normales para crear un subproceso (o ExecutionService).

+1

Ah, Chris me ganó. – Thilo

+0

Vota de todos modos. ¡Gracias! – SquareCog

2

Me gustaría hacer un pequeño cambio a la respuesta muy detallada que dio Chris; Establecería myThread como un hilo de Daemon por myThread.setDaemon(true);, que básicamente mantendrá el hilo activo mientras haya otros subprocesos no Daemon en funcionamiento que necesiten el hilo de fondo. Cuando todos estos subprocesos finalizan, la JVM detiene su subproceso Daemon y usted no necesita manejarlo usted mismo en contextDestroyed. Pero eso son solo mis 2 centavos.

+13

Excepto que aún necesita manejarlo en contexto destruido. Los daemons finalizan cuando finaliza el último subproceso no daemon, no cuando finaliza el contexto de servlet. Si despliega un archivo WAR para reemplazar uno que se está ejecutando actualmente, el subproceso de daemon del contexto de servlet anterior se seguirá ejecutando. A su vez, mantiene el ClassLoader de ese contexto, que es una pérdida de memoria PermGen, que es malo. –

5

Poner <load-on-startup>1</load-on-startup> en el bloque <servlet> en su web.xml obligará init() de nuestro servlet suceda tan pronto como se inicia Tomcat hacia arriba, en lugar de esperar para la primera solicitud en llegar. Esto es útil si desea engendrar el hilo de fondo desde init().

+0

Esto me sirvió de algo, tan simple en comparación con otras soluciones aquí, pero sin clasificar y adecuado para iniciar algunas aplicaciones en segundo plano o demonios. ¡Gracias! –

1

Otra forma si está utilizando un marco basado en resorte puede especificar la clase/hilo que desea inicializar en beans.xml. Entonces, cuando se inicia Tomcat, beans.xml inicializará todas las clases mencionadas en él. También puede pasar argumentos de constructor si es necesario. A continuación se muestra el ejemplo de lo mismo.

beans.xml

<bean id="monitoringSvc" class="com.mypackage.MonitoringService"> 
    <constructor-arg value="60"></constructor-arg> 
</bean> 

MonitoringService.java

public class MonitoringService{ 

    private MyThread myThread; 

    public MonitoringService(int seconds){ 
      myThread = new MyThread(seconds); 
      myThread.start(); 
    } 
}  
Cuestiones relacionadas