【问题标题】:Calling servlet's destroy method调用servlet的destroy方法
【发布时间】:2012-11-06 09:33:49
【问题描述】:

根据链接http://www.xyzws.com/Servletfaq/when-is-destroy-of-servlets-called/20,调用destroy方法的原因之一是servlet长时间没有收到请求

我在想可能有一些页面很长一段时间都没有被调用。那么,这是否意味着将调用 destroy 并且不再使用它们?

其实我在面试中被问到这个问题,他告诉我destroy方法只有在服务器关闭时才会被调用。

感谢您对此的任何帮助。

【问题讨论】:

  • 我认为杀死一个 servlet 不是你的责任。这不应该是你的责任,这就是为什么你在一个 servlet 容器中,而一个 servlet 是一个托管资源

标签: java jakarta-ee servlets destroy


【解决方案1】:

阿法伊克,

在 java servlet 中,destroy() 不应该被程序员调用。但是,如果它被调用,它就会被执行。隐含的问题是,servlet 会被破坏吗?不,它不会。 destroy() 方法不应该也不会破坏 java servlet。

java servlet 中destroy() 的含义是,内容在容器决定销毁servlet 之前执行。但是如果你自己调用destroy() 方法,内容就会被执行,然后相应的过程会继续。对于这个问题,destroy() 被执行,然后 servlet 初始化完成。

destroy()方法首先被调用,然后Servlet被从容器中移除,最后被垃圾回收。 destroy() 方法通常包含释放任何资源(如 JDBC 连接)不会被垃圾回收的代码。

【讨论】:

    【解决方案2】:

    几个案例:

    1. 当容器关闭或应用程序关闭时;
    2. 当容器判断内存不足时;
    3. 当这个 servlet 很长时间没有收到请求时。

    根据文档

    由 servlet 容器调用以向 servlet 指示 servlet 正在停止服务。该方法只调用一次 servlet 服务方法中的所有线程都已退出或在 超时时间已过。在 servlet 容器调用这个之后 方法,它不会在这个 servlet 上再次调用服务方法。

    【讨论】:

      【解决方案3】:

      来自规范(The Servlet Interface -> Servlet Life Cycle -> End of Service):

      一旦在 servlet 实例上调用了 destroy 方法,容器可能不会路由 对该 servlet 实例的其他请求。如果容器需要启用 再次使用 servlet,它必须使用 servlet 类的新实例。

      规范是指正在被销毁的 servlet 的特定实例。

      那么,这是否意味着将调用destroy并且不再使用它们?

      这并不意味着其实例被销毁的 servlet 永远不会被使用。只有那个特定的实例没有被使用,因为它会被垃圾收集。当该 servlet 收到请求时,容器将创建该 servlet 的新实例并执行所有生命周期操作,直到再次为请求提供服务。

      【讨论】:

        【解决方案4】:

        来自 Servlet 规范:-

        destroy() 方法由 servlet 容器调用以向 servlet 指示 servlet 正在停止服务。只有在 servlet 的服务方法中的所有线程都退出或经过超时时间之后,才会调用此方法。 servlet容器调用destroy()方法后,不会在“THIS SERVLET”上再次调用service方法。

        servlet 容器不需要在任何特定时间段内保持加载 servlet。 servlet 实例可以在 servlet 容器中保持活动状态几毫秒,在 servlet 容器的生命周期内(可能是几天、几个月或几年),或两者之间的任何时间。

        当 servlet 容器确定应该从服务中删除一个 servlet 时,它会调用 Servlet 接口的 destroy 方法以允许 servlet 释放它正在使用的任何资源并保存任何持久状态。例如,当容器想要节省内存资源或正在关闭时,可能会这样做。

        在servlet容器调用destroy方法之前,它必须允许servlet的service方法中当前运行的任何线程完成执行,或者超过服务器定义的时间限制。

        一旦对 servlet 实例调用了 destroy 方法,容器就不能将其他请求路由到该 servlet 实例。

        如果容器需要再次启用 servlet,它必须使用 servlet 类的新实例。

        【讨论】:

          【解决方案5】:

          这是那些经典的规范与实现的事情之一。规范允许像 Tomcat 这样的 Servlet 容器维护一个 Servlet 对象池,在负载上升或下降时创建和销毁它们。在这种设置中,当不再需要特定实例时会调用destroy。为每个请求创建一个新实例甚至在处理请求之前立即调用 init 并在之后立即销毁也是合法的。

          但实际上,实际上每个 Servlet 容器都只维护每个 Servlet 的一个实例。由于要求 Servlet 是线程安全的,所以这也完全没问题。在这种情况下,只有在上下文关闭时才会调用destroy。

          我想不出很多情况下您会希望汇集 Servlet,但规范允许这样做。

          【讨论】:

            【解决方案6】:

            这完全取决于您使用的 servlet 容器的实现。如果你的 servlet 容器对于节省资源非常保守,它可能会破坏长时间不服务的 servlet。

            在 servlet spec 2.5 的第 22 页,你会发现,“当 servlet 容器确定应该从服务中删除一个 servlet 时,它会调用 Servlet 接口的 destroy 方法以允许 servlet 释放它所拥有的任何资源使用和保存任何持久状态。例如,当容器想要节省内存资源或正在关闭时,可能会这样做。"

            【讨论】:

              【解决方案7】:

              Servlet.destroy() 的 javadoc 说:“由 servlet 容器调用以向 servlet 指示 servlet 正在停止服务”。它没有指定什么情况会导致 servlet “停止服务”,它只是一个事件,您可以在需要时对其做出反应。例如,您可能想要关闭一些已打开的资源,或将某些状态保存到存储中。

              最明显的原因是 servlet 容器正在关闭,但容器同样可以决定是时候卸载 servlet,因为它在一个月内没有使用,只是在消耗资源。这种行为完全取决于实现,而不是您(作为 servlet 设计者)应该关心的事情。

              【讨论】:

                【解决方案8】:

                Servlet 的destroy 方法是一个回调。这些是容器在特定事件即将发生时调用的函数(在这种情况下,servlet 即将被销毁)。因此,整个目的是如果您想做某事(例如:清理资源),您可以在此回调下执行这些操作。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-10-16
                  • 1970-01-01
                  • 2015-10-29
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-04-23
                  相关资源
                  最近更新 更多