2009-04-27 89 views
58

我对Tomcat并不是很熟悉,在我的脑海中,它基本上被抽象为一个cgi服务器,它可以在调用之间保存JVM - 但我知道它可以做的远不止这些。Tomcat servlet应用程序的后台线程

我正在寻找一种方式Tomcat服务器启动时启动背景线程,这将定期更新服务器环境(在我的这个特殊的情况是听一些其他服务和更新的可用性,心跳线程信息,但人们可以想象它有多种用途)。

有没有一个标准的方法来做到这一点? Context的启动和更新/查询都是?

任何指向相关文档和/或代码示例的指针都将非常感谢。

+0

值得注意的是,当你想要的时候,你通常可以启动一个线程,如果有比上下文初始化更方便的地方。例如。它可能在特定servlet的init方法中,或者当某个类首先被初始化等。 – 2009-04-27 05:34:36

回答

77

如果您希望在WAR部署启动一个线程,可以在web.xml中定义一个上下文监听器:

<web-app> 
    <listener> 
     <listener-class>com.mypackage.MyServletContextListener</listener-class> 
    </listener> 
</web-app> 

然后实现类是这样的:

public class MyServletContextListener implements ServletContextListener { 

    private MyThreadClass myThread = null; 

    public void contextInitialized(ServletContextEvent sce) { 
     if ((myThread == null) || (!myThread.isAlive())) { 
      myThread = new MyThreadClass(); 
      myThread.start(); 
     } 
    } 

    public void contextDestroyed(ServletContextEvent sce){ 
     try { 
      myThread.doShutdown(); 
      myThread.interrupt(); 
     } catch (Exception ex) { 
     } 
    } 
} 
+0

啊!谢谢,这非常简单。 我正确地说“ServletContext”是我需要修改的,让这个线程将信息传递给我的servlet,因此它可以使用我的心跳监听器收集的状态? – SquareCog 2009-04-27 01:52:56

+1

是的,在我的答案中错过了这部分。 :) ServletConext可以从ServletContextEvent中获得,它可以传递给你的Thread对象,它可以获取/设置所有线程的属性。 – 2009-04-27 02:07:39

+0

那时,如何访问`MyServletContextListener`来查询线程? – 2016-11-23 15:04:44

12

我正在寻找一种方式来启动一个后台线程,当一个Tomcat服务器启动

我想你正在寻找一种启动后台线程的方式,你的web应用程序由Tomcat启动。

这可以使用ServletContextListener来完成。它在web.xml中注册,并且会在您的应用程序启动或停止时调用。然后,您可以使用普通的Java方法创建(并稍后停止)线程,以创建线程(或ExecutionService)。

+1

啊,克里斯击败了我.. – Thilo 2009-04-27 01:49:05

2

我只是对克里斯给出的非常详细的答案做一个小小的修改;我将myThread设置为一个Daemon线程myThread.setDaemon(true);,只要您有其他非守护线程工作需要您的后台线程,它就会基本保持线程处于活动状态。当所有这些线程完成后,您的守护程序线程将被JVM停止,您不需要在contextDestroyed中自行处理它。 但这只是我的2美分。

5

<load-on-startup>1</load-on-startup>置于您的web.xml中的<servlet>块中会迫使您的servlet的init()在Tomcat启动后立即发生,而不是等待第一个请求到达。如果你想从init()产生后台线程,这很有用。

1

另一种方法,如果您使用基于弹簧的框架,您可以指定要在beans.xml中初始化的类/线程。所以当tomcat启动时,beans.xml将初始化它中提到的所有类。如果需要,您也可以传递构造函数参数。下面是同样的例子。

的beans.xml

<bean id="monitoringSvc" class="com.mypackage.MonitoringService"> 
    <constructor-arg value="60"></constructor-arg> 
</bean> 

MonitoringService。java

public class MonitoringService{ 

    private MyThread myThread; 

    public MonitoringService(int seconds){ 
      myThread = new MyThread(seconds); 
      myThread.start(); 
    } 
}