How to get and set a global object in Java servlet context

拜拜、爱过 提交于 2019-11-27 13:13:46
Michael

Yes, I would store the list in the ServletContext as an application-scoped attribute. Pulling the data from a database instead is probably less efficient, since you're only updating the list every hour. Creating a ServletContextListener might be necessary in order to give the Quartz task a reference to the ServletContext object. The ServletContext can only be retrieved from JavaEE-related classes like Servlets and Listeners.

EDIT: In the ServletContextListener, when you create the job, you can pass the list into the job by adding it to 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");
    //...
  }
}

You can try some caching solution, like EhCache to store you values, and update them every hour. It will handle concurrency issues. The cache object itself can be stored in the ServletContext

A good way to write to the ServletContext from the Quartz job is to register listeners to your job that get notified about the changed value. So for example:

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

Your Job will have a List<JobListener> and when you schedule the job, you instantiate the concrete listener and add it to the job.

Well, if you use static fields they will be visible to all classes loaded by the same class loader. I think that at least the servlets of one app should end up qualifying. However, this is admittedly dirty.

An object that is defined and guaranteed to be (more) global is the ServletContext. This is shared between all servlets forming part of one application, i.e. loaded from the same web.xml. There are put and get calls for ServletContext that allow you treat it essentially as a Map.

Beyond that, you'll need to find classes common to all Web apps inside one Tomcat server. Tomcat does a lot of footwork with loaders, and I think different Web apps will have distinct loaders. You can get around this by writing a class of your own and placing that class in Tomcat's common or shared directories. If I understand this description correctly, those classes will be made available, ONCE, to all Web apps.

Finally, beyond the confines of a single Tomcat server, you'll need some TCP/IP based mechanism for communicating between JVMs. But as I understood your question, that shouldn't be necessary.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!