【问题标题】:Managing resource closure in a servlet container管理 servlet 容器中的资源关闭
【发布时间】:2010-06-15 02:18:31
【问题描述】:

我使用 Tomcat 作为 servlet 容器,并部署了许多 WAR。许多 WAR 共享公共基类,由于不同的类加载器等原因,这些基类在每个上下文中被复制。

如何确保在上下文销毁时清理资源,而无需挂钩每个 web.xml 文件以添加上下文侦听器?

理想情况下,我想要一些类似

的东西
class MyResourceHolder implements SomeListenerInterface {
    private SomeResource resource;
    {
        SomeContextThingie.registerDestructionListener(this);
    }
    public void onDestroy() { resource.close(); }
}

可以在每个 web.xml 中添加一些内容,但由于可能存在许多 WAR,并且只有实际初始化资源的 WAR 需要清理它,所以在以下情况下注册清理似乎更自然资源被初始化而不是复制大量的 XML 配置然后也许清理。

(在这种特殊情况下,我正在启动一个 SQL 连接池的有序关闭。但我认为这在许多其他情况下也很有用......)

我确信那里有一些非常明显的解决方案,但我的 Google-fu 现在让我失望了。谢谢!

【问题讨论】:

    标签: java tomcat servlets


    【解决方案1】:

    除了ServletContextListener,没有其他可行的选择。

    如果您已经在使用 Servlet 3.0,那么您只需使用 @WebListener 对其进行注释,将其与 webapp 一起发布,它将自动加载。但是对于 Servlet 2.5 及更早版本,您真的需要麻烦web.xml

    【讨论】:

    • 该死。还没有使用 3.0,实际上 Tomcat 6 似乎不支持它。看起来几年后会容易得多:-p
    • Tomcat 7.0 支持它。这几乎是最终的。您可以通过 SVN here 获取 RC。
    • Tomcat 7 于 6 月 29 日进入测试阶段。因此有一个官方下载页面:tomcat.apache.org/download-70.cgi
    【解决方案2】:

    您可以将资源放在共享类加载器中,并将它们作为 JNDI 资源提供 - 但您必须非常小心地通过这样做来保持您的应用程序同步 - 尽管这是一种选择。

    可能取决于您要清理的资源类型,以及您希望在 API 中看到的流失类型。

    注意:类加载器问题可能很难调试 - “Class XClass 不是 XClass 的实例”会让你发疯。

    Edit1: 另一个选项:您可以在您的池或其他对象上使用终结器 - 这应该允许您执行代码(例如当一个 webapp 被卸载并且池被回收时) - 这就是如何许多 JDK 类清理本地资源。如果你这样做了,要非常小心,因为终结器队列上的死锁会阻塞各种重要的清理,并且可能会使你的 JVM 崩溃,因为使用终结器的任何东西都不会被 gc'd。

    【讨论】:

    • 是的,类加载器很痛苦。我会这样做,但我不想介绍 JNDI 的额外复杂性并实际共享资源,因为系统已经很复杂且难以理解!
    • 好吧,除非共享类加载器,否则尝试在多个类加载器中处理资源清理是非常不干净的。你也可以使用终结器 - 非常小心 - 终结器队列上的死锁会杀死你的系统 - 我将编辑答案以包含它。
    【解决方案3】:

    将您的 SQL 连接池从 Web 应用程序中移到 Web 容器中,并通过 JNDI 访问它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多