使用servlet在Java EE环境中启动和停止ScheduledExecutorService

我们需要使用简单的servlet应用程序通过JMX监视远程JVM详细信息。 所以在一个独立的应用程序中完成的工作是

1)创建一个JMX连接器并获取内存数据 – >完成2)我们需要不断监视和获取记录(2.1>可以被视为计划任务的恒定延迟并将记录插入DB或2.2>是否JMX给出了历史记录,如果是,哪个MBean可以访问该信息?)。

在这里,我打算使用一个界面来注册域,然后就可以了。 有来自JSP的启动和停止按钮。 我们点击启动系统时的function将运行调度程序(ScheduledExecutorService)并在后台捕获记录以提供历史记录。 当使用点击停止时,调度程序必须停止后台进程。 问题是我们如何控制和获取调度程序的对象?

1)换句话说,我们如何通过servlet启动和停止ScheduledExecutorService? 从一个servlet启动一个线程并从一个特定任务的另一个servlet中停止一个线程?

2)如果我们有集群/负载平衡环境怎么办?

目前我正在考虑将每个ScheduledExecutorService添加到HashMap中,关键是任务对象和值是使用SingleTon设计模式的ScheduledExecutorService。 有没有默认方法。 使用SingleTon的整个循环处于集群/负载平衡环境中,我们可能无法获得适当的更新对象。

期待您的宝贵建议。

如果在java ee 7上,请尝试使用javax.enterprise.concurrent.ManagedScheduledExecutorService

然后,您可以执行资源注入并使用类似于下面的代码启动任务。

 @Resource ManagedScheduledExecutorService mses; public void startTask() { mses.scheduleAtFixedRate(runnable, 10, 10, SECONDS); } 

在Java EE 6中,您可以使用timerservice API创建/删除servlet

ServletContext

ServletContext表示您在Servlet容器中运行的整个Web应用程序。 在Servlet处理第一个HTTP请求之前建立上下文,如Servlet规范所承诺的那样。 虽然HttpSession代表每个用户的工作会话(从技术上讲,是一个通过servlet代码的线程),但ServletContext代表所有这些用户的范围。

要挂钩servlet上下文的设置和拆除,请实现ServletContextListener 。 提示:通过使用@WebListener注释对其进行标记来自动部署侦听器。 该接口需要一对方法,每个方法在您处理第一个Servlet请求之前以及当您的Web应用程序被拆除之前设置Web应用程序时调用。

提示:该拆卸方法是关闭ScheduledExecutorService的好地方。 在您的Web应用程序结束后,与您的执行程序服务关联的线程可能会存在。 你可能不希望这种情况发生。

请参阅此问题: 如何在Java servlet上下文中获取和设置全局对象

另请参阅BalusC 对Servlet范围的这个很好的总结 。

获取servlet上下文

您可以通过首先访问其ServletConfig来访问当前servlet的ServletConfig

 // … in your Servlet, such as its request handler methods like `doGet` … ServletContext sc = this.getServletConfig().getServletContext() ; 

那么在ServletContextListener ,我们如何访问servlet上下文? 当调用侦听器上的两个方法中的任何一个时,将传递ServletContextEvent 。 从那里调用ServletContextEvent::getServletContext()

将对象存储为servlet上下文中的“属性”

那么在哪里存储您的Web应用程序的全局变量,例如ScheduledExecutorService ? servlet上下文具有StringObject的内置映射。 这些被称为“属性”。 调用setAttribute( String , Object )来存储属性映射。 因此,为ScheduledExecutorService创建一个名称,以便在此映射中使用密钥。

 ScheduledExecutorService sec = … ; // Instantiated somewhere in your code. … String key = "myScheduledExecutorServiceForXYZ" ; sc.setAttribute( key , sec ); // Storing the executor service as a generic `Object` for use later. 

稍后您可以以相同的方式获取ScheduledExecutorService 。 您需要从Object转换为已知类,在本例中为ScheduledExecutorService

 Object o = sc.getAttribute( key ); // Fetch the `ScheduledExecutorService` from the servlet context's built-in map of attributes. // Cast to known class. If in doubt, test first with [`instanceOf`][11]. ScheduledExecutorService sec = ( ScheduledExecutorService ) o ; 

您可以通过调用ServletContext::getAttributeNames来请求所有存储的属性名称的列表。

范围图

下面是我的图表,以了解Servlet环境中范围的层次结构。 注意每个范围层如何具有其属性集,它自己的String to Object映射。 在图表中,每组属性的寿命都较短。

在此处输入图像描述