ThreadLocal 返回 null,即使在 HandlerInterceptor 中设置之后

问题描述 投票:0回答:0

我的 ThreadLocal 变量在 HandlerInterceptor 中为每个 request 设置,但有时它在服务层访问时返回 null 而不是预期值。

我假设 ThreadLocal 对象是 thread safe 并且对于单个请求线程是本地的。因此,即使有多个请求正在设置/清除它,它也只会为那个特定的请求线程被清除,而不会影响其他线程。

但是 1-2 次(现在无法重现,即使有很多日志语句)在调试模式下,我遇到服务层中的ThreadLocal为空(因此得到一个NullPointerException),即使它不应该因为它是在 HandlerInceptor 中设置的,它总是在 spring-boot 的控制器层之前先命中。

下面是ThreadLocal代码真正线程安全的,当多个请求线程同时访问它时。

是否有可能Interceptor在一个Thread中执行并且控制器在另一个线程中执行并且在拦截器设置ThreadLocal中的值之前控制器线程以某种方式首先执行。

代码:

ThreadLocal.class

@Component
public class ThreadLocalUtil {

    private static final ThreadLocal<ConstantsConfig> constantsConfig = new ThreadLocal<>();

    public static ConstantsConfig getConstantsConfig() {
        return constantsConfig.get();
    }

    public static void setConstantsConfig(ConstantsConfig config) {
        constantsConfig.set(config);
    }

    public static void clearConstantsConfig() {
        constantsConfig.remove();
    }
}

HandlerInceptor.class

public class RequestInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (request.getRequestURI().equals(ControllerEndpoints.HEALTH)) {
        return true;
    }
    // we are always setting ThreadLocal, before accessing it in service layer.
    setConstants(request);
    logThreadLocal();
    return true;
}

private void setConstants(HttpServletRequest request) {          
     ThreadLocalUtil.setConstantsConfig(BeanUtil.getBean(ImplConstantsConfig.class))
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception {
    if (request.getRequestURI().equals(ControllerEndpoints.HEALTH)) {
        return;
    }

    ThreadLocalUtil.clearConstantsConfig();
}

AccessorService.class

// accessed in multiple service classes for 1 request/response cycle.
ThreadLocalUtil.getConstantsConfig().getProperty1()
ThreadLocalUtil.getConstantsConfig().getProperty2()
java spring interceptor servlet-filters thread-local
© www.soinside.com 2019 - 2024. All rights reserved.