java - 删除 Spring MVC 网站中的 ThreadLocal 对象?

标签 java spring-mvc thread-local

我有以下类(class):

public class AppContext {
        
    private static final ThreadLocal<AppContextData> contextHolder = new ThreadLocal<AppContextData>() {
        
        @Override
        protected AppContextData initialValue() {
            return new AppContextData();
        }
    };
    
    public static AppContextData get() {
        return contextHolder.get();
    }
    
    public static void unset() {
        contextHolder.remove();
    }
}

public class AppContextData {
   //many getter and setter methods
}

网站开始在拦截器中使用 ThreadLocal 对象,并在整个 Web 请求中使用该对象。

public class MyIntercepter extends HandlerInterceptorAdapter {
            
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  {
    
        AppContext.get();
        //..... 
    }
}

我在 Tomcat 8.x 上运行该网站,发现日志中有以下错误消息。

20-May-2016 22:43:53.657 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [my.organization.data.AppContext$1] (value [my.organization.data.AppContext$1@31d4463a]) and a value of type [my.organization.data.AppContextData] (value [my.organization.data.AppContextData@e89d5f4]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

如何解决这个问题?

最佳答案

JanPi 已经在评论中说了我们必须做的事情。如果有人想知道如何,这里是:

public class MyIntercepter extends HandlerInterceptorAdapter {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  {
        AppContext.get();
        //..... 
    }

    public void afterCompletion(
        HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        AppContext.unset();
    }

    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        // only relevant when a handler starts an asynchronous request.
        AppContext.unset();
    }
}

postHandle 方法看起来是个好地方,但 afterCompletion 更好,因为即使处理程序无法正确处理请求(也称为发生异常),它也会被调用。

关于java - 删除 Spring MVC 网站中的 ThreadLocal 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37358426/

相关文章:

java - 使用 Spring 返回空的 ResponseEntity 的最佳方法是什么?

java - 从 Spring MVC 端点流式传输动态图像而不将其保存在内存中

java - ThreadLocal 用于多线程访问 SimpleDateFormat

java - Clojure中的线程局部变量

java - java中的PDF打印

java - 如何检查Java中变量的类型?

java - Android从原始共享按钮音频

java - org.hibernate.hql.internal.ast.QuerySyntaxException : unexpected token: * near line 1

java - @Autowired 请求处理失败;嵌套异常是 java.lang.NullPointerException

java - 我们真的需要在ThreadLocal中设置Transaction吗?