Java 如何在ServletContextListener出现异常时中止Tomcat启动?

Java 如何在ServletContextListener出现异常时中止Tomcat启动?,java,tomcat,servlets,decorator,Java,Tomcat,Servlets,Decorator,我有一个类实现了ServletContextListener,它在启动时加载一些资源 这些资源对于应用程序来说至关重要,当我的逻辑中发生一些不好的事件时,我希望整个启动都失败 在ServletContextListener.contextInitialized()方法中,我是否可以执行任何命令来停止整个Tomcat启动并使其失败?尝试指定: -Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true 在java运行时选项中,引用: 如果为tr

我有一个类实现了
ServletContextListener
,它在启动时加载一些资源

这些资源对于应用程序来说至关重要,当我的逻辑中发生一些不好的事件时,我希望整个启动都失败

ServletContextListener.contextInitialized()
方法中,我是否可以执行任何命令来停止整个Tomcat启动并使其失败?

尝试指定:

-Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true
java
运行时选项中,引用:

如果为true,则如果在服务器初始化阶段发生异常,服务器将退出

如果未指定,将使用默认值false

更新:

如果要通过代码执行此操作,
System.exit()
是否有效

public class FailFastListener implements ServletContextListener {
    
    private static final Logger log = LoggerFactory.getLogger(FailFastListener.class);
    
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        try {
            //initialization
        } catch(Exception e) {
            log.error("Sooo bad, shutting down", e);
            System.exit(1);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}

您可以使用模式包装现有侦听器,而不会使它们混乱。不确定Tomcat将如何反应…

如果您想停止Tomcat,因为您的Web应用程序部署失败,我假设您没有其他应用程序部署到Tomcat。在这种情况下,为什么不将此应用程序构建为一个带有嵌入式Tomcat/Jetty的独立Web应用程序?这样,只要你的webapp不能正常启动,嵌入式服务器也会关闭

在我看来,您似乎专注于
ServletContextListener
来解决一个并非
ServletContextListener
所要解决的问题

不要使用
System.exit()
,因为它会杀死可能运行其他已部署应用程序的服务器。如果因为你知道永远不会有其他应用程序(而且你不想),那么就制作一个独立的webapp。CWE中将这种不良做法列为潜在的弱点:

提示:spring boot有助于构建带有嵌入式服务器的独立webapp。请参阅本指南:


很好的文章解释了为什么这可能是您想要的:

谢谢,这几乎解决了我的问题,但是。。。我希望通过代码执行来完成它。如果不可能-我将使用运行时选项。是:)魔法系统。退出(1):)我知道,我应该以更清晰的方式向我提问。。。所以有没有办法通过检索Tomcat容器来实现这一点?主要原因我担心System.exit不会关闭生命周期中的其他事件,例如其他侦听器“销毁”代码。。。您对此有何看法?启用安全管理器后,System.exit()将不起作用。是否有人找到System.exit(1)以外的其他方法-Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true在这种情况下不起作用,因为contextInitialized方法中的异常不被视为服务器故障,而只是servlet故障。不要使用System.EXIT。这在CWE知识库中被列为坏习惯:CWE-382:J2EE坏习惯:使用System.exit()除了System.exit(1)之外,还有人找到其他方法吗?@Bastien,使用SpringBoot@Leo无关的对这个问题的正确答案是解释SpringBoot是如何处理这个问题的。@Bastien,我不认为发表评论是详细阐述这个问题的好地方。我提到springboot只是为了简短。解决方案实际上是使用嵌入式web容器创建一个独立的webapp。请看下面我的答案。@Leo我做了,但你只是提供了一个解决方法,而不是解决眼前的问题。我给了你一个高分,因为你基本上是正确的,但是Tomcat是一种特殊情况,因为嵌入式Tomcat并不总是真正嵌入的。。。也就是说,仍然使用多个类加载器。例如,Tomcat Maven插件将把一个WAR转换成一个可执行的JAR,但实际上它的运行与普通Tomcat非常相似。SpringBoot不这样做,因为它是父级,Tomcat在同一个类加载器中运行。拥有多个类加载器(TomcatMaven插件方式)实际上有一个好处,因为您可以避免TomcatsJAR的问题(例如它在日志中的选择)。