2016-04-29 215 views
0

在我的spring-jdbc项目中,我有一个名为DBStuff的类,用于连接数据库并进行简单的数据库操作。这是一个Web项目,并有用户,所以自然我使用会话机制。当我需要在DBStuff类检索请求数据,我使用这行代码如下:RequestContextHolder线程安全吗?

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 

但是,没有解释,如果RequestContextHolder是线程安全与否。即使春天的官方forum也没有答案。由于使用servlet,我需要为用户提供线程安全性。

根据定义RequestContextHolder定义为“Holder类以线程绑定RequestAttributes对象的形式公开Web请求。”但我不确定是否“线程绑定”代表线程安全。

+0

这是线程安全的,但你为什么你的数据访问层绑定到你的web层...这是一种代码异味,你做错了一个信号。 –

+0

我的DataAccess层和Web层是独立的,但每个用户请求都保留其登录数据,这在数据库操作中起着巨大的作用。我应该将DataAccess类更改为原型吗?但是,如果我这样做,是不是会为我的系统花费太多内存和性能? –

+0

不,他们没有分开...你的数据层依赖于web层。你不能把你的dbaccess类放到非web启用的服务器上,因为它与Spring的'javax.servlet'和Web相关的包紧密耦合。因此,网络和数据访问之间的耦合。如果你需要的话,或者在方法参数中传递这些东西,或者将它存储在一个'ThreadLocal'中,但是不要泄漏Web绑定类中的其他任何东西。 –

回答

4

“线程绑定”意味着每个线程都拥有自己的数据副本,因此它是线程安全的。

它使用ThreadLocal对于

private static final ThreadLocal<RequestAttributes> requestAttributesHolder = 
     new NamedThreadLocal<RequestAttributes>("Request attributes"); 

public static RequestAttributes getRequestAttributes() { 
    RequestAttributes attributes = requestAttributesHolder.get(); 
    if (attributes == null) { 
     attributes = inheritableRequestAttributesHolder.get(); 
    } 
    return attributes; 
} 

requestAttributesHolder.get()当前线程返回RequestAttributes,它是处理一个请求HTTP一个线程。每个请求都有自己的线程。的ThreadLocalget()

方法使用地图来绑定的数据到Thread.currentThread()

public T get() { 
    Thread t = Thread.currentThread(); 
    ThreadLocalMap map = getMap(t); 
    if (map != null) { 
     ThreadLocalMap.Entry e = map.getEntry(this); 
     if (e != null) 
      return (T)e.value; 
    } 
    return setInitialValue(); 
} 

When and how should I use a ThreadLocal variable?

+0

但是类DBStuff是单例的,是不是让RequestContextHolder绑定到这个类的线程? –

+0

如果我有这个要求,并且在课堂上继续下去,这是真的。但问题是我尝试在这个单例'DBStuff'类中获取请求。如果'RequestContextHolder'绑定到当前线程,那么它如何处理两个同时发生的请求呢? –

+0

@cihanseven我更新 –