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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3215988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:29:48  来源:igfitidea点击:

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

javaservletsquartz-scheduler

提问by Mr Morgan

I wonder if anyone can advise: I have a scenario where a scheduled job being run by Quartz will update an arraylist of objects every hour.

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

But I need this arraylist of objects to be visible to all sessions created by Tomcat. So what I'm thinking is that I write this object somewhere every hour from the Quartz job that runs so that each session can access it.

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

Can anyone say how best this may be achieved? I was wondering about the object being written to servlet context from the Quartz job? The alternative is having each session populate the arraylist of objects from a database table.

任何人都可以说如何最好地实现这一目标?我想知道从 Quartz 作业写入 servlet 上下文的对象?另一种方法是让每个会话从数据库表中填充对象的数组列表。

Thanks

谢谢

Mr Morgan.

摩根先生。

采纳答案by Michael

Yes, I would store the list in the ServletContextas 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 ServletContextListenermight be necessary in order to give the Quartz task a reference to the ServletContextobject. The ServletContextcan only be retrieved from JavaEE-related classes like Servlets and Listeners.

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

EDIT: In the ServletContextListener, when you create the job, you can pass the list into the job by adding it to a JobDataMap.

编辑:在 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");
    //...
  }
}

回答by Carl Smotricz

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.

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

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 putand getcalls for ServletContext that allow you treat it essentially as a Map.

定义并保证(更多)全局的对象是ServletContext。这在构成一个应用程序一部分的所有 servlet 之间共享,即从同一个web.xml. 有putget调用 ServletContext 允许您将其本质上视为 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 commonor shareddirectories. If I understand this descriptioncorrectly, those classes will be made available, ONCE, to all Web apps.

除此之外,您还需要在一台 Tomcat 服务器中找到所有 Web 应用程序通用的类。Tomcat 在加载器方面做了很多工作,我认为不同的 Web 应用程序会有不同的加载器。您可以通过编写自己的类并将该类放在 Tomcatcommonshared目录中来解决此问题。如果我正确理解了这个描述,这些类将一次性提供给所有 Web 应用程序。

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.

最后,超出单个 Tomcat 服务器的范围,您将需要一些基于 TCP/IP 的机制来在 JVM 之间进行通信。但据我了解你的问题,这应该没有必要。

回答by Bozho

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

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

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

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

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.

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