java - servlet - request.setattribute jsp
Cómo obtener y establecer un objeto global en el contexto del servlet de Java (3)
Me pregunto si alguien puede recomendar: tengo un escenario en el que un trabajo programado que está ejecutando Quartz actualizará una lista de objetos cada hora.
Pero necesito que esta lista de objetos sea visible para todas las sesiones creadas por Tomcat. Entonces, lo que estoy pensando es que escribo este objeto en algún lugar cada hora desde el trabajo de Quartz que se ejecuta para que cada sesión pueda acceder a él.
¿Alguien puede decir cómo se puede lograr esto mejor? Me preguntaba si el objeto se estaba escribiendo en el contexto de servlet desde el trabajo de Quartz. La alternativa es que cada sesión complete la lista de objetos de una tabla de base de datos.
Gracias
Sr. Morgan.
Bueno, si utiliza campos estáticos, serán visibles para todas las clases cargadas por el mismo cargador de clases. Creo que al menos los servlets de una aplicación deberían terminar por calificar. Sin embargo, esto es ciertamente sucio.
Un objeto que se define y se garantiza que es (más) global es el ServletContext . Esto se comparte entre todos los servlets que forman parte de una aplicación, es decir, cargados desde el mismo web.xml
. Hay llamadas de put
y get
para ServletContext que le permiten tratarlo esencialmente como un mapa.
Más allá de eso, deberá encontrar clases comunes a todas las aplicaciones web dentro de un servidor Tomcat. Tomcat hace mucho trabajo de pie con cargadores, y creo que diferentes aplicaciones web tendrán cargadores distintos. Puede solucionar esto escribiendo una clase propia y colocando esa clase en los directorios common
o shared
Tomcat. Si entiendo esta descripción correctamente, esas clases estarán disponibles, una vez, para todas las aplicaciones web.
Finalmente, más allá de los confines de un único servidor Tomcat, necesitará algún mecanismo basado en TCP / IP para comunicarse entre las JVM. Pero como entendí tu pregunta, eso no debería ser necesario.
Puede probar alguna solución de almacenamiento en caché, como EhCache para almacenar sus valores y actualizarlos cada hora. Se encargará de los problemas de concurrencia. El objeto de caché en sí puede almacenarse en el ServletContext
Una buena manera de escribir en el ServletContext
desde el trabajo de Quartz es registrar a los oyentes en su trabajo para que se les notifique sobre el valor cambiado. Así por ejemplo:
public class JobListener {
public void updateValue(Object newValue);
}
public class ServletContextCacheJobListener implements JobListener {
private ServletContext ctx;
public ServletContextJobListener(ServletContext ctx) {
this.ctx = ctx;
}
public void updateValue(Object newValue) {
Cache cache = (Cache) ctx.getAttribute("cache");
cache.update("yourKey", newValue);
}
}
Su trabajo tendrá una List<JobListener>
y cuando programe el trabajo, creará una instancia del oyente concreto y lo agregará al trabajo.
Sí, almacenaría la lista en el ServletContext
como un atributo de ámbito de aplicación. En cambio, extraer los datos de una base de datos es probablemente menos eficiente, ya que solo se actualiza la lista cada hora. La creación de un ServletContextListener
puede ser necesaria para dar a la tarea de Quartz una referencia al objeto ServletContext
. El ServletContext
solo se puede recuperar de clases relacionadas con JavaEE como Servlets y Listeners.
EDITAR: en el ServletContextListener, cuando crea el trabajo, puede pasar la lista al trabajo agregándolo a un JobDataMap.
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent event){
ArrayList list = new ArrayList();
//add to ServletContext
event.getServletContext().setAttribute("list", list);
JobDataMap map = new JobDataMap();
map.put("list", list);
JobDetail job = new JobDetail(..., MyJob.class);
job.setJobDataMap(map);
//execute job
}
public void contextDestroyed(ServletContextEvent event){}
}
//Quartz job
public class MyJob implements Job{
public void execute(JobExecutionContext context){
ArrayList list = (ArrayList)context.getMergedJobDataMap().get("list");
//...
}
}