我正在使用Tomcat作为servlet容器,并且部署了许多WAR。许多WAR共享公共基类,由于不同的类加载器等,它们在每个上下文中都会被复制。
如何在不挂钩每个web.xml文件以添加上下文侦听器的情况下确保上下文销毁时的资源清理?
理想情况下,我喜欢
的内容class MyResourceHolder implements SomeListenerInterface {
private SomeResource resource;
{
SomeContextThingie.registerDestructionListener(this);
}
public void onDestroy() { resource.close(); }
}
我可以在每个web.xml中添加一些东西,但由于可能有很多WAR而且只有实际初始化资源的那些需要清理它,所以在注册清理时似乎更自然资源已初始化,而不是复制大量的XML配置,然后可能清理。
(在这种特殊情况下,我正在启动SQL连接池的有序关闭。但我发现这在许多其他情况下也很有用......)
我确信那里有一些非常明显的解决方案,但我的Google-fu现在让我失望了。谢谢!
答案 0 :(得分:2)
除ServletContextListener
之外没有其他可行的选择。
如果您已经使用Servlet 3.0,那么您可以使用@WebListener
对其进行注释,并将其与webapp一起发送,它将自动加载。但是对于Servlet 2.5及更早版本,你真的需要对web.xml
进行麻烦。
答案 1 :(得分:1)
您可以将资源放在共享类加载器中并将它们作为JNDI资源使用 - 您必须非常小心地通过这样做来保持应用程序同步 - 尽管这是一个选项。
可能取决于您要清理哪种资源,以及您期望在API中看到哪种流失。
注意:类加载器问题可能很难调试 - “类XClass不是XClass的实例”会让你疯狂。
Edit1:另一个选项:您可以在池或其他对象上使用终结器 - 这应该允许您执行代码(例如卸载Web应用程序并回收池时) - 这就是许多JDK类清理本机资源。如果你这样做,要非常小心,因为终结器队列上的死锁将阻止所有类型的重要清理,并可能导致你的JVM崩溃,因为没有使用终结器的东西会得到gc'd。
答案 2 :(得分:0)
将SQL连接池移出Web应用程序并移入Web容器,然后通过JNDI访问它。