有没有办法在关闭时使用 ContextListener 关闭 contextDestroyed() 方法中的所有 ThreadLocals(保存 Session 对象)?

Is there a way to close all the ThreadLocals (saving Session object) in contextDestroyed() method using ContextListener at the time of shutdown?

我在我的应用程序中遇到内存泄漏(TOMCAT v9),如下所示:

2019 年 9 月 25 日 17:40:34.752 严重 [Thread-10] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks Web 应用程序 [] 创建了一个 ThreadLocal,键类型为 [java.lang.ThreadLocal](值 [ java.lang.ThreadLocal@7c606bab]) 和类型 [org.hibernate.internal.SessionImpl] 的值(值 [SessionImpl(56310373)]),但在 Web 应用程序停止时未能将其删除。线程将随着时间的推移而更新,以尝试避免可能的内存泄漏。

每次我们打开会话对象时,我都尝试关闭会话对象,但由于编码中使用的标准不足,我面临各种 Hibernate 级别的异常,因为某些对象被延迟获取,并关闭会话导致意外异常。

现在,如果可能的话,我正在尝试使用 contextListener 来实现同样的事情,而不用担心关闭每个会话对象。

我试过使用 System.gc() 但它似乎没有释放那些 ThreadLocal 对象。

能否请您提出一些在关闭时使用 Listener 或任何其他可能的方法来摆脱这些对象的方法?

网络请求完成后,您应该关闭 Hibernate 会话并将其从 ThreadLocal 中删除。

由于您似乎在生成响应时遇到了延迟加载问题(JSP?),您需要在 响应完全生成后执行此操作.

您可以在 Servlet 中做到这一点 Filter。确保这是 您拥有的任何其他过滤器之前,因此会话将作为 last 步骤关闭。

public final class SessionCloseFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        try {
            chain.doFilter(request, response);
        } finally {
            try {
                // Close and remove session here
            } catch (Exception e) {
                // Log but don't throw the exception
            }
        }
    }

}