Come ottenere e impostare un object globale nel contesto del servlet Java

Mi chiedo se qualcuno può consigliare: ho uno scenario in cui un lavoro programmato gestito da Quartz aggiornerà un arraylist di oggetti ogni ora.

Ma ho bisogno che questo arraylist di oggetti sia visibile a tutte le sessioni create da Tomcat. Quindi quello che sto pensando è che scrivo questo object da qualche ora dal processo Quartz che viene eseguito in modo che ogni sessione possa accedervi.

Qualcuno può dire quanto possa essere meglio ottenerlo? Mi chiedevo se l’object fosse scritto nel contesto di servlet dal lavoro Quartz? L’alternativa è che ogni sessione popola l’array di oggetti da una tabella di database.

Grazie

Mr Morgan.

Sì, vorrei archiviare l’elenco in ServletContext come attributo con ambito applicazione. Il prelievo dei dati da un database è probabilmente meno efficiente, in quanto si aggiorna l’elenco solo ogni ora. La creazione di un ServletContextListener potrebbe essere necessaria per assegnare all’attività Quartz un riferimento all’object ServletContext . ServletContext può essere recuperato solo dalle classi correlate a JavaEE come Servlet e Listener.

MODIFICA: in ServletContextListener, quando si crea il lavoro, è ansible passare l’elenco nel lavoro aggiungendolo a 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"); //... } } 

Puoi provare una soluzione di caching, come EhCache, per memorizzare valori e aggiornarli ogni ora. Gestirà i problemi di concorrenza. L’object cache stesso può essere memorizzato nel ServletContext

Un buon modo per scrivere su ServletContext dal processo Quartz è registrare i listener del tuo lavoro che ricevono una notifica sul valore modificato. Quindi per esempio:

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

Il tuo lavoro avrà un List e quando pianifichi il lavoro, istanzia l’ascoltatore concreto e lo aggiungi al lavoro.

Bene, se si usano campi statici, saranno visibili a tutte le classi caricate dallo stesso programma di caricamento classi. Penso che almeno i servlet di un’app dovrebbero finire per qualificarsi. Tuttavia, questo è certamente sporco.

Un object definito e garantito (più) globale è ServletContext . Questo è condiviso tra tutti i servlet che fanno parte di un’applicazione, cioè caricati dallo stesso web.xml . Esistono chiamate get e get per ServletContext che consentono di trattarlo essenzialmente come una mappa.

Oltre a ciò, dovrai trovare le classi comuni a tutte le app Web all’interno di un server Tomcat. Tomcat fa un sacco di footwork con i caricatori, e penso che diverse app Web avranno caricatori distinti. Puoi aggirare questo problema scrivendo una tua class e inserendo quella class nelle directory common o shared di Tomcat. Se capisco correttamente questa descrizione , tali classi saranno rese disponibili, UNA VOLTA, a tutte le app Web.

Infine, oltre i confini di un singolo server Tomcat, avrai bisogno di un meccanismo basato su TCP / IP per comunicare tra JVM. Ma come ho capito la tua domanda, non dovrebbe essere necessario.