具体来说,当我的Web应用程序无法初始化时(由于配置错误),我希望Tomcat中止启动。
到目前为止,我唯一的选择是System.exit(-1)
。这确实有效,但我担心对Tomcat这样做会导致问题。
Tomcat旨在抵御那些无法启动的编写错误的应用程序。
org.apache.catalina.startup.EXIT_ON_INIT_FAILURE用于在Tomcat的某个组件(例如其中一个连接器)未启动时停止Tomcat(例如,因为该端口正在使用中)。
System.exit()是丑陋的,但它会起作用,就Tomcat来说它是安全的(至于kill -9)。应用程序可能不喜欢这种相当残酷的关闭方法。
有一种Tomcat特定的方法可以更干净地完成这项工作。将自定义LifecycleListener添加到服务器组件并让它响应AFTER_START_EVENT。让侦听器将Container层次结构从服务器导航到上下文[服务器 - >服务 - >引擎 - 主机 - >上下文],并检查每个上下文是否处于STARTED状态。如果没有,请在服务器上调用stop()然后destroy()。
正如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>
你的观点1你的意思是你从调用tomcat shutdown.bat文件的应用程序抛出未初始化的状态异常。你试图从程序中调用shutdown.bat文件。
我知道这个问题有点老了,但我会在这里进一步思考开箱即用的解决方案。看起来您的要求是在您的webapp无法初始化时停止tomcat。这与“中止Tomcat启动”略有不同。 Tomcat本身已经启动,并将在启动后立即开始部署您的webapp。根据您的要求,我假设您没有任何其他Web应用程序。如果是这样的话,你为什么不只使用Spring Boot? Spring引导提供了一种部署自包含Web应用程序的方法。在这种情况下,如果初始化失败,应用程序将无法启动。