2

具体来说,我希望 Tomcat 在我的 Web 应用程序无法初始化(由于配置错误)时中止启动。

  1. 我尝试使用 Tomcat 关闭端口。当我的网络应用程序启动时,它还没有准备好。

  2. -Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true,不起作用。Tomcat 启动得很好。

  3. 抛出一个未捕获的异常。我试过抛出异常。Tomcat 仍然正确初始化,但我的 Web 应用程序处于非功能状态。

  4. 使用 Tomcat JMX API。任何关闭方法都不会导致 Tomcat 关闭。

到目前为止,我唯一的其他选择是System.exit(-1). 这确实有效,但我担心对 Tomcat 这样做会导致问题。

4

4 回答 4

5

Tomcat 的设计目的是对编写不佳且无法启动的应用程序具有弹性。

org.apache.catalina.startup.EXIT_ON_INIT_FAILURE 用于在 Tomcat 的组件之一(例如连接器之一)未启动(例如,因为端口正在使用中)时停止 Tomcat。

System.exit() 很难看,但它会起作用,而且就 Tomcat 而言它是安全的(至于那件事是 kill -9)。应用程序可能不喜欢这种相当残酷的关闭方法。

有一种 Tomcat 特定的方法可以更干净地执行此操作。将自定义 LifecycleListener 添加到 Server 组件并让它响应 AFTER_START_EVENT。让侦听器将容器层次结构从服务器导航到上下文 [Server->Service(s)->Engine-Host(s)->Context(s)] 并检查每个上下文是否处于 STARTED 状态。如果没有,请在服务器上调用 stop() 然后 destroy()。

于 2013-05-04T18:45:25.493 回答
1

正如 Mark Thomas 所提到的,这是中止 Tomcat 启动的侦听器的实现。StrictStateCheckListener是一个启动后的服务器监听器。它检查所有Container的状态,包括引擎、主机和上下文。如果有任何组件未能启动(状态不同于STARTED),服务器启动将被中止。

package com.example.lifecycle;

import java.util.logging.*;
import org.apache.catalina.*;

public class StrictStateCheckListener implements LifecycleListener {

  private static final Logger LOGGER = Logger.getLogger(StrictStateCheckListener.class.getName());

  private boolean hasFailures;

  private String containerState;

  @Override
  public void lifecycleEvent(LifecycleEvent event) {
    String type = event.getType();
    Lifecycle lifecycle = event.getLifecycle();

    if (lifecycle instanceof Server && type.equals(Lifecycle.AFTER_START_EVENT)) {
      Server server = (Server) lifecycle;
      hasFailures = false;

      // Check status of each container
      StringBuilder sb = new StringBuilder("Status:").append(System.lineSeparator());
      for (Service service : server.findServices()) {
        checkState(service.getContainer(), sb, "");
      }
      if (LOGGER.isLoggable(Level.INFO)) {
        LOGGER.info(sb.toString());
      }
      if (hasFailures) {
        /*
         * The server will not be stopped by this listener. Indeed,
         * an exception is raised to trigger shutdown hook. See:
         * `org.apache.catalina.startup.Catalina`.
         */
        throw new IllegalStateException(containerState);
      }
    }
  }

  private void checkState(Container container, StringBuilder report, String indent) {
    if (!hasFailures && container.getState() != LifecycleState.STARTED) {
      hasFailures = true;
      containerState = stateOf(container);
    }
    report.append(indent).append(stateOf(container));
    for (Container child : container.findChildren()) {
      checkState(child, report, indent + "  ");
    }
  }

  private String stateOf(Container container) {
    String className = container.getClass().getSimpleName();
    String stateName = container.getStateName();
    return String.format("%s[%s]: %s%n", className, container.getName(), stateName);
  }
}

通过以下方式将此侦听器注册到您的服务器组件server.xml

<Server>
  ...
  <Listener className="com.example.lifecycle.StrictStateCheckListener" />
  ...
</Server>
于 2018-03-04T14:23:26.490 回答
0

您的第 1 点您的意思是当您正在调用 tomcat shutdown.bat 文件的应用程序抛出未初始化状态异常时。您是否尝试从程序中调用 shutdown.bat 文件。

于 2013-05-04T09:04:50.000 回答
0

我知道这个问题有点老了,但我会在这里更进一步思考你正在寻找的解决方案。看起来您的要求是在您的 webapp 无法初始化时停止 tomcat。这与“中止 Tomcat 启动”有点不同。Tomcat 本身已经启动,将在启动后立即开始部​​署您的 webapp。根据您的要求,我假设您没有任何其他 web 应用程序。如果是这样,为什么不直接使用 Spring Boot?Spring Boot 提供了一种部署自包含 Web 应用程序的方法。在这种情况下,如果初始化失败,应用程序将无法启动。

于 2016-08-11T20:44:42.380 回答