【问题标题】:Clean up after servlet if init() failed如果 init() 失败,则在 servlet 后清理
【发布时间】:2010-12-22 01:40:26
【问题描述】:

我有一个实现ServletContextListener 接口的Initializer 类。在它的contextInitialized()方法中,我初始化了一些必须销毁的全局类,否则无法卸载servlet。

然而,当 servlet 的 init() 方法抛出 ServletException 时,contextDestroyed() 方法永远不会被调用 --> 资源不会被释放 --> servlet 不会被 Tomcat 卸载(它仍然处于“运行状态”状态,即使它的 init 方法从未完成)。

我的问题是——在这种情况下如何清理资源?

奖励:为什么 servlet 甚至会进入“运行”状态?我从the documentation 了解到,除非init() 方法成功完成,否则它不应该运行。

编辑 - 我认为这是因为 Tomcat 管理器中显示的每个状态行都代表整个战争,而不是 servlet。一场战争可能包含多个 servlet,其中一些成功启动,而另一些则没有。 Initializer 在容器启动时被调用,它的destroy 仅在整个容器被丢弃时被调用。这就引出了一个相关的问题——是否有类似的内置方法来监控单个 servlet 的状态?

(我知道我可以编写自定义代码来监视 servlet,无论是否通过 JMX,但这超出了 这个问题)。

【问题讨论】:

    标签: java tomcat servlets


    【解决方案1】:

    在现实世界中,init() 永远不会失败。如果它失败了,那么它是一个开发人员应该修复的编程错误。 appserver webcontainer 与它无关。 servlet 将保持不可用。

    【讨论】:

    • 这是配置/部署错误,而不是编程错误。那么如何监控 servlet 的状态呢?
    • 配置错误仍然是您的责任。只需读取日志即可进行监控。
    • 我看不出这有什么关系。我们的运维人员正在监控的部分内容是容器状态。我们认为它代表 servlet 状态,但显然不是。剩下的唯一问题是,如果 Tomcat 中的所有 servlet 都无法启动,是否应该停止容器。
    【解决方案2】:

    你在运行什么容器?

    例如,Tomcat 确实支持JMX。您始终可以编写自己的 JMX-bean。

    【讨论】:

    • Tomcat,正如我在问题中所述。我知道我可以编写自定义(JMX 或不)代码来监控它,但这超出了这个问题的范围 - 我想知道是否有现成的解决方案。
    【解决方案3】:

    据我所知,如果没有外部请求,绝对没有办法这样做。 ServletContextListener 为您提供正确的信号(当所有 servlet 都已初始化 - 成功与否),但您无法枚举上下文中的所有 servlet 以测试它们的状态,因为相关的 ServletContext 方法已被弃用,现在返回一个空的枚举器。

    简而言之,做到这一点的唯一方法是通过非标准 API;尤其是,使用 Tomcat 的 JMX API 来做这件事几乎是微不足道的,这是我推荐的课程。

    【讨论】:

    • 根据ServletContextListener 的javadoc,contextInitialized 方法是“在Web 应用程序中的任何过滤器或servlet 初始化之前”驱动的,这与方法名称中的过去时可能会导致您相信。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 1970-01-01
    • 2020-05-22
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多