參考資料: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列表的形式存在的。