contextDestroyed方法何时被调用?

18

实现了一个 ContextListener之后,我现在可以愉快地处理contextDestroyed事件,关闭连接池并刷新缓存等。

最近当我的服务器没有被关闭时,contextDestroyed被调用了,这让我很惊讶——它似乎是在某个我无法追踪的随机时间调用的。

是否有任何定义的事件或一组触发contextDestroyed的情况?

contextDestroyed被调用时,我应该确保我的所有操作都是可逆的吗?我需要让所有的连接池在destroyed/initialized周期中幸存下来吗? 我错了以为只有在关闭Tomcat或替换我的war时才会收到contextDestroyed吗?


我想这是来自@Kayaman标签的ServletContextListener - christopher
啊,是的,我没有看标签。关键在于它真的是ServletContext而不是ServerContext。尽管当服务器关闭时所有servlet上下文肯定都会被销毁,但这并不意味着servlet上下文不能在其他时间被销毁(例如长时间未使用时)。您使用哪个服务器?您可以通过参数来控制销毁。 - Kayaman
Servlet Lifecycle 允许容器删除上下文,例如回收资源,因此最好检查Tomcat是否允许您控制行为。 - Kayaman
ServletContext不仅仅是单个servlet,它是“MyWebappContext”。理论上J2EE服务器可以卸载空闲的Web应用程序,但我还没有遇到过。但是,您可以在不重启应用程序服务器的情况下启动Web应用程序重新部署。编辑mywebapp/web-inf/文件,管理员面板重新启动点击,运行时复制或删除新的mywebapp/web-inf/lib/.jar文件,删除webapps/mywebapp.war文件或替换它。大多数J2EE服务器都支持这种热部署方式。 - Whome
@christopher - 是的,它是一个ServletContextListener - OldCurmudgeon
1
@Whome - 如果我删除了.war文件,那么在Tomcat清理之前我会得到一个contextDestroyed。干净地复制一个新的.war文件可以重新启动一切,并且我能够生存下来,因为所有的单例池都会被重新创建。我的问题是,我现在发现我偶尔会得到一个没有静态数据刷新的contextDestroyed,这会导致各种损坏,甚至需要重新启动Tomcat才能恢复。 - OldCurmudgeon
2个回答

10

通过一系列的试错测试,我发现当以下情况发生时,contextDestroyed()会被调用:

  1. 服务器正在更新/移除 .WAR 文件。
  2. 服务器由于管理员干预而关闭。
  3. 服务器由于编程错误而关闭。某些将终止非服务器应用程序的东西。

如果您遇到问题#3,正如您所建议的那样,我认为最好的做法是安全地(确保不创建无限循环)调用contextInitialized()以确保池被正确重新创建。


有趣的第三点 - 你在测试中是如何引起这种情况的?不幸的是,我的连接池创建速度不够快,很难为了 contextDestroyed 而重新构建它们。 - OldCurmudgeon
1
其实很简单...我的代码出了问题。我“故意”引入了一个无法完成的SQL查询,没有有效的ResultSet它就不能next()并抛出了一个NullPointerException,这反过来导致程序终止,而没有杀死Tomcat进程。我假设你的错误与SQL无关,但这是我的发现。我还假设,由于这个问题已经快一年了,你已经解决了这个问题。 - glend
实际上,我无法解决它 - 这是一个我避免的独特情况。问题归结为由于错误的库版本引起的类加载器崩溃,因此我删除了导致问题的依赖项。感谢您宝贵的经验。 - OldCurmudgeon
@glend你说的关闭方式是指在终端中使用./catalina.sh stop吗?我还没有机会在Eclipse之外的设置中进行测试。我正在使用一个ServletContextListener,其中包含在“初始化”和“销毁”上下文中运行的代码。但是当我主动停止服务器时(在Eclipse中按下小红色方块),方法“destroyed”中的代码似乎不会运行。我知道当您列表中的第1点发生时:更新/删除时,它会运行,因为它会写出简单的sysout。你有什么想法吗?也许是我设置的Eclipse的原因? - brat
@brat,抱歉我很久没有使用Tomcat了,我记不清了。您可以尝试创建另一个问题或尝试发布日志。 - glend
@glend 考虑在监听器中启动一个线程,定期备份数据。绕过了我遇到的问题x)。感谢您的回复,非常感激。 - brat

3

1
谢谢您的回复,但我的问题是关于任何其他情况下contextDestroyed可能被调用。我无法重现这个问题,但是从记忆中我看到contextDestroyed由于Tomcat中的类加载器异常而在循环中被调用。我找不到任何具体的合同来说明contectDestroyed将在什么时候被调用 - 只有您引用的那种情况,并且没有进一步的解释。 - OldCurmudgeon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接