如何从 Java 干净地启动和停止 Tomcat,为什么我的方式不能重复工作?



我正在编写一个Quartz应用程序,该应用程序在Windows上运行,并调用Lucene和Solr来运行索引作业。它运行一系列作业,每个作业由以下步骤组成:

  1. 确保Tomcat已停止(在Tomcat下运行的Solr可防止删除或复制索引目录)
  2. 如有必要,删除旧索引目录
  3. 启动Tomcat
  4. 确保Tomcat和Solr应用程序正在运行
  5. 运行索引作业
  6. 停止Tomcat
  7. 确保Tomcat已停止
  8. 将索引目录复制到存档

我决定让启动和停止Tomcat的代码设置在Startup.bat、Shutdown.bat和Catalina.bat中设置的系统属性,并使用"start"one_answers"stop"参数调用Bootstrap.main。这在一次迭代中有效,但当我尝试Quartz运行时却没有,在Quartz中我设置了两次迭代。

当我的代码在第一次迭代结束时关闭Tomcat时,显示了所有常见的消息,包括

INFO: Stopping ProtocolHandler ["http-bio-5918"]

(我使用的是5918端口),但当它在第二次迭代开始时尝试启动Tomcat时,它得到了错误:

SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-5918"]
java.net.BindException: Address already in use: JVM_Bind <null>:5918

SEVERE: Failed to initialize connector [Connector[HTTP/1.1-5918]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-5918]]

我在命令提示符窗口中运行了netstat-an,它确认5918端口正在使用中。我用来检查Tomcat是否正在运行的代码没有什么特别之处。我在互联网上看到过很多地方。

public boolean isTomcatRunning(String url) {
  boolean isRunning = false;
  try {
    new URL(url).openConnection().connect();
    isRunning = true;
  } catch (IOException e) {
    isRunning = false;
  }
  return isRunning;
}

但它显然告诉我Tomcat在运行时并没有运行

正如我所说,我通过调用Bootstrap.main(newString[]{"start"})和Bootstrap.main(newString[]{"stop"}。唯一奇怪的是,当我简单地调用Bootstrap.main(newString[]{"start"})时,它似乎不会返回(我还没有等足够长的时间来查看它是挂起还是花了很长时间),所以我一直在线程中运行它。

也许这就是问题的原因,因为Catalina.bat看起来没有做任何特别的事情,而且它从启动时就很好地返回了。我想知道我是否需要做一个额外的设置,使它能够在主线程中运行启动而不挂起。

无论如何,这就是我对从Quartz应用程序中启动和停止Tomcat感到困惑的地方,如果您能提供任何帮助和建议,我将不胜感激。

我强烈建议您使用一个控制Tomcat实例生命周期的包装器来包装Tomcat实例。这样的包装器就是Java服务包装器。较旧的版本(3.2.3我相信)是"免费的",可以很好地与较新的Tomcat实例配合使用。

然后,您的控制应用程序与包装器"对话"以启动/停止Tomcat应用程序。这种方法有多种好处。其中之一是,您不受Tomcat应用程序挂起和正在测试的端口不再回复的影响。

最新更新