Servlets 如何使ServletContextListener停止JavaEE应用程序?

Servlets 如何使ServletContextListener停止JavaEE应用程序?,servlets,jakarta-ee,servlet-listeners,Servlets,Jakarta Ee,Servlet Listeners,我有一个ServletContextListener,它在Java EE应用程序启动时执行一些数据库管理功能。这在启动/加载JPA和应用程序的其他部分之前在我的应用程序中运行。如果数据库维护失败,我将记录错误。如果数据库维护失败,应用程序将无法正常运行,我想停止应用程序 如何从ServletContextListener.contextInitialized优雅而正确地停止应用程序 下面维文给出的解决方案很接近,但并不完全正确。当我抛出RuntimeException时,Glassfish处于不

我有一个ServletContextListener,它在Java EE应用程序启动时执行一些数据库管理功能。这在启动/加载JPA和应用程序的其他部分之前在我的应用程序中运行。如果数据库维护失败,我将记录错误。如果数据库维护失败,应用程序将无法正常运行,我想停止应用程序

如何从ServletContextListener.contextInitialized优雅而正确地停止应用程序


下面维文给出的解决方案很接近,但并不完全正确。当我抛出RuntimeException时,Glassfish处于不一致的状态,其管理控制台不可访问,但某些进程仍在运行并保持端口3700(IIOP?)打开,从而阻止重新启动。

如果您的
ServletContextListener
抛出异常,webapp无法正确加载,应用服务器可能会阻止所有后续请求(并以500错误响应)

这并不是阻止应用程序启动,也不是阻止应用程序停止,但它阻止了应用程序的进一步使用,在您的情况下可能会很有用

在规范中经过适当验证后,此行为在规范中不是强制性的。服务器可能(不必)返回500个错误。因此,必须谨慎使用该解决方案


有关Servlet规范的引用,请参阅。在侦听器中,捕获任何异常并使用Servlet上下文属性存储有关错误的标志或其他有用信息。您可能还应该记录一些东西,表明该应用程序不起作用

此时,您的选项可能由应用程序的体系结构决定。如果所有请求都由单个控制器/调度程序servlet处理,那么让其
init
方法检查上下文属性并抛出
UnavailableException
可能是有意义的。请注意,异常只适用于抛出它的特定servlet。如果您的应用程序包含许多servlet或允许直接访问其他资源,那么这种方法将变得不易管理


另一个选项是创建一个过滤器,该过滤器拦截每个请求,检查上下文属性,然后抛出异常。当然也可能有其他变体。

“如果您的ServletContextListener引发异常,则Web应用程序无法正确加载”-您如何知道这一点?规范没有定义这样的东西。同样,任何给定的应用程序服务器都会简单地报告异常并继续运行
ServletContextListener
不是为了影响应用程序的生命周期而设计的。第11.6段描述了这一点:“监听器异常”。-“容器可能会用HTTP状态代码500响应Web应用程序的所有后续请求,以指示应用程序错误。”啊,很公平。您可能希望使用URL和引用来限定原始答案。不过,这种语言太模糊了,我不想依赖于“容器可能会响应”。我刚刚意识到它实际上是说“可能”,而不是“必须”。不像我第一次想的那么准确…抛出
运行时异常
不会停止应用服务器。它可能会阻止应用程序启动,并且可能会使用500(服务器错误)响应代码响应所有后续的应用程序请求。使用
System.exit
是一个非常糟糕的主意。即使在同一台服务器上部署了其他(正常工作的)应用程序,它也会强制关闭服务器。我曾经处理过这样的应用程序(露天),相信我,这不仅仅是烦人!在我的监听器中,我设置了一个上下文属性,然后在过滤器中对此做出反应。过滤器抛出一个ServletException(HTTP 500),它停止UI,但不停止我的Web服务。有什么地方我可以实现一个过滤器(或类似的)来检查这个上下文属性吗?不知道停止Web服务是什么意思。如果过滤器配置为拦截每个请求,则每个请求都应导致异常。你能提供一些关于你应用程序的webservices部分的详细信息吗?我的webservices都使用EnterpriseBeans,而UI使用Servlets/ActionBeans。因此,对于UI,我有一个可以检查此应用程序状态的过滤器。对于EnterpriseBeans,我必须实现类似于Iterceptor的东西来检查应用程序状态并做出适当的响应。