参考资料:https://www.bilibili.com/video/BV1Ki4y1t7Va?t=4507
1.spring项目在开发过程中用的都是数据库连接池,这样可以避免线程的消耗,
之前说过spring的事务问题,事务保证了操作的一致性,那么线程安全是怎么保证的呢?
底层用的ThreadLocal来保证线程之间的数据隔离
当一个线程开启事务时,会从连接池取一个连接 放到与自己绑定的ThreadLocal中,这个线程在service和dao层中获取连接时直接从ThreadLocal中获取,最后执行完了会把连接放回到线程池中。
源码:查看spring事务管理的DataSourceTransactionManager类的doBegin方法。
然后
点开resources,发现是一个ThreadLocal对象
再点发现这个NameThreadLocal类继承自ThreadLocal,只是多了一个名字。
这个类在spring中哪里用了呢?可以看到,spring中大量使用了ThreadLocal
注:ThreadLocal是跟线程(通过线程id)绑定的,ThreadLocal是用来暂时存放数据的。
用法如下,在很多的登录安全框架中就是用的ThreadLocal来保存用户信息,如:security,因此在获取用户信息的时候才能获取当前线程对应的ThreadLocal对应的用户信息,
通过ThreadLocal来隔离用户信息,ThreadLocla是每个线程的实例,因此每个线程的ThreadLocal内容都是不一样的,spring通过ThreadLocal实现线程之间隔离,通过
单例模式来减少资源的消耗。
在我的项目中,ThreadLocal和session是传递用户信息的:
流程如下:
配置过滤器,在过滤器中从session中获取用户信息,然后存到ThreadLocal中,所以同一个线程获取的用户信息是一样的,因为session在同一客户端也是一样的,所以不同线程之前也能共享同一个用户信息。
注意理解request请求,session,以及生命周期:
每一个request就是一个线程,在web项目中这些个线程都是由Tomcat线程池管理,一次请求结束后request的生命周期也就结束了,
要延长request的生命周期可以用forward,但是redirect不行。
而Session是整个会话期间,注意,不同客户端的创建session的时候返回的JSESSIONID是不一样的,这就说明session也是不一样的,
session在服务器中是以session列表的形式存在的。