如何在Java servlet上下文中获取和设置全局对象

时间:2010-07-09 19:39:19

标签: java servlets quartz-scheduler

我想知道是否有人可以提供建议:我有一个场景,Quartz运行的预定作业每小时都会更新一个对象的arraylist。

但我需要这些对象的arraylist对Tomcat创建的所有会话都是可见的。所以我想的是我每小时从运行的Quartz作业中的某个地方写这个对象,以便每个会话都可以访问它。

有人可以说这可以达到最佳效果吗?我想知道从Quartz作业写入servlet上下文的对象?另一种方法是让每个会话从数据库表中填充对象的arraylist。

由于

摩根先生。

3 个答案:

答案 0 :(得分:13)

是的,我会将列表存储在ServletContext中作为应用程序范围的属性。从数据库中提取数据可能效率较低,因为您每小时只更新一次列表。可能需要创建ServletContextListener才能为Quartz任务提供对ServletContext对象的引用。 ServletContext只能从与Servlet和Listeners等JavaEE相关的类中检索。

编辑: 在ServletContextListener中,创建作业时,可以通过将列表添加到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");
    //...
  }
}

答案 1 :(得分:1)

您可以尝试一些缓存解决方案,例如EhCache来存储您的值,并每小时更新一次。它将处理并发问题。缓存对象本身可以存储在ServletContext

从Quartz作业写入ServletContext的好方法是将监听器注册到您的作业,以获得有关更改值的通知。例如:

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

您的作业将有一个List<JobListener>,当您安排作业时,您将实例化具体的侦听器并将其添加到作业中。

答案 2 :(得分:0)

好吧,如果你使用静态字段,它们对同一个类加载器加载的所有类都是可见的。我认为至少一个应用程序的servlet应该最终符合条件。然而,这无疑是肮脏的。

定义并保证(更多)全局的对象是ServletContext。这在构成一个应用程序的一部分的所有servlet之间共享,即从相同的web.xml加载。 ServletContext有putget次调用,允许您将其视为Map。

除此之外,您还需要找到一个Tomcat服务器内所有Web应用程序的通用类。 Tomcat在加载器方面做了很多步法,我认为不同的Web应用程序会有不同的加载器。您可以通过编写自己的类并将该类放在Tomcat的commonshared目录中来解决这个问题。如果我正确理解this description,那么这些类将可用于所有Web应用程序。

最后,除了单个Tomcat服务器的限制之外,您还需要一些基于TCP / IP的机制来在JVM之间进行通信。但是,正如我理解你的问题,这不应该是必要的。