Tomcat中session詳解(原始碼閱讀)
Tomcat中的session是通過一個manager來管理的,其中Session介面預設實現類有StandardSession,管理器的預設實現是StandardManager。
我們平時在servlet中使用的session也就是HashMap中的一個session物件,同時session除了在記憶體儲存,同時還提供了持久化方法,tomcat中持久化有兩種,一種是儲存為檔案,另一種則是儲存到資料庫。
這一節首先來看一下預設的StandardSession和StandardManager。
public interface Session {
// ----------------------------------------------------- Manifest Constants
public static final String SESSION_CREATED_EVENT = "createSession";
public static final String SESSION_DESTROYED_EVENT = "destroySession";
// ------------------------------------------------------------- Properties
public String getAuthType();
public void setAuthType(String authType);
public long getCreationTime();
public void setCreationTime(long time);
public String getId();
public void setId(String id);
public String getInfo();
public long getLastAccessedTime();
public Manager getManager();
public void setManager(Manager manager);
public int getMaxInactiveInterval();
public void setMaxInactiveInterval(int interval);
public void setNew(boolean isNew);
public Principal getPrincipal();
public void setPrincipal(Principal principal);
public HttpSession getSession();
public void setValid(boolean isValid);
public boolean isValid();
// --------------------------------------------------------- Public Methods
public void access();
public void addSessionListener(SessionListener listener);
public void expire();
public Object getNote(String name);
public Iterator getNoteNames();
public void recycle();
public void removeNote(String name);
public void removeSessionListener(SessionListener listener);
public void setNote(String name, Object value);
}
1.StandardManager中整個啟動過程
public void start() throws LifecycleException {
if (debug >= 1)
log("Starting");
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("standardManager.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Force initialization of the random number generator
if (debug >= 1)
log("Force random number initialization starting");
String dummy = generateSessionId();
if (debug >= 1)
log("Force random number initialization completed");
// Load unloaded sessions, if any
try {
//用於載入持久化的session,載入以後放入sessions(hashMap)中
load();
} catch (Throwable t) {
log(sm.getString("standardManager.managerLoad"), t);
}
// Start the background reaper thread
threadStart();
}
//啟動一個管理器執行緒,用於實現自動重新載入
private void threadStart() {
if (thread != null)
return;
threadDone = false;
threadName = "StandardManager[" + container.getName() + "]";
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.setContextClassLoader(container.getLoader().getClassLoader());
thread.start();
}
/**
* The background thread that checks for session timeouts and shutdown.
*/
public void run() {
// Loop until the termination semaphore is set
while (!threadDone) {
threadSleep();
processExpires();
}
}
private void threadSleep() {
try {
Thread.sleep(checkInterval * 1000L);
} catch (InterruptedException e) {
;
}
}
/**
* Invalidate all sessions that have expired.
*/
//管理StandardSession中session,去除無效的session
private void processExpires() {
long timeNow = System.currentTimeMillis();
//獲取存活的sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
//有效,則不移除
if (!session.isValid())
continue;
int maxInactiveInterval = session.getMaxInactiveInterval();
//如果設定最大存活時間是-1,則不終止
if (maxInactiveInterval < 0)
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle >= maxInactiveInterval) {
try {
session.expire();
} catch (Throwable t) {
log(sm.getString("standardManager.expireException"), t);
}
}
}
}
2.StandardManager中整個停止過程
public void stop() throws LifecycleException {
if (debug >= 1)
log("Stopping");
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("standardManager.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
// Stop the background reaper thread
threadStop();
// Write out sessions
try {
//將存活的session持久化
unload();
} catch (IOException e) {
log(sm.getString("standardManager.managerUnload"), e);
}
// Expire all active sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
if (!session.isValid())
continue;
try {
//終止所有的session
session.expire();
} catch (Throwable t) {
;
}
}
// Require a new random number generator if we are restarted
this.random = null;
private void threadStop() {
if (thread == null)
return;
threadDone = true;
//將當前執行緒設定為中斷狀態
thread.interrupt();
try {
//當前執行緒被掛起,直達thread執行緒結束才執行改執行緒
thread.join();
} catch (InterruptedException e) {
;
}
thread = null;
}
1.StandardManager中建立一個session
public Session createSession() {
if ((maxActiveSessions >= 0) &&
(sessions.size() >= maxActiveSessions))
throw new IllegalStateException
(sm.getString("standardManager.createSession.ise"));
//實際呼叫的是ManagerBase中的creatSession()方法
return (super.createSession());
}
//ManagerBase類中creatSession方法
public Session createSession() {
// Recycle or create a Session instance
Session session = null;
synchronized (recycled) {
int size = recycled.size();
if (size > 0) {
session = (Session) recycled.get(size - 1);
recycled.remove(size - 1);
}
}
if (session != null)
session.setManager(this);
else
session = new StandardSession(this);
// Initialize the properties of the new session and return it
session.setNew(true);
session.setValid(true);
session.setCreationTime(System.currentTimeMillis());
session.setMaxInactiveInterval(this.maxInactiveInterval);
String sessionId = generateSessionId();
String jvmRoute = getJvmRoute();
// @todo Move appending of jvmRoute generateSessionId()???
if (jvmRoute != null) {
sessionId += '.' + jvmRoute;
session.setId(sessionId);
}
/*
synchronized (sessions) {
while (sessions.get(sessionId) != null) // Guarantee uniqueness
sessionId = generateSessionId();
}
*/
session.setId(sessionId);
return (session);
}
相關文章
- Tomcat中Lifecycle詳解(原始碼閱讀)Tomcat原始碼
- Express Session 原始碼閱讀筆記ExpressSession原始碼筆記
- Tomcat原始碼閱讀筆記Tomcat原始碼筆記
- 【詳解】ThreadPoolExecutor原始碼閱讀(三)thread原始碼
- 【詳解】ThreadPoolExecutor原始碼閱讀(二)thread原始碼
- 【詳解】ThreadPoolExecutor原始碼閱讀(一)thread原始碼
- Tomcat 原始碼閱讀記錄(1)Tomcat原始碼
- Caddy 原始碼閱讀(一)Run 詳解原始碼
- 【原始碼閱讀】AndPermission原始碼閱讀原始碼
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- 從koa-session原始碼解讀session原理Session原始碼
- 完全解析!Bert & Transformer 閱讀理解原始碼詳解ORM原始碼
- ARTS第十三週(閱讀Tomcat原始碼)Tomcat原始碼
- tomcat8.5.57原始碼閱讀筆記1Tomcat原始碼筆記
- Laravel核心解讀–Session原始碼解析LaravelSession原始碼
- go 中 select 原始碼閱讀Go原始碼
- 【Tomcat】Tomcat原始碼閱讀之StandardHost與HostConfig的分析Tomcat原始碼
- 【原始碼閱讀】Glide原始碼閱讀之with方法(一)原始碼IDE
- 【原始碼閱讀】Glide原始碼閱讀之into方法(三)原始碼IDE
- Tomcat聯結器執行過程(原始碼閱讀)Tomcat原始碼
- ReactorKit原始碼閱讀React原始碼
- AQS原始碼閱讀AQS原始碼
- CountDownLatch原始碼閱讀CountDownLatch原始碼
- HashMap 原始碼閱讀HashMap原始碼
- delta原始碼閱讀原始碼
- 原始碼閱讀-HashMap原始碼HashMap
- NGINX原始碼閱讀Nginx原始碼
- Mux 原始碼閱讀UX原始碼
- HashMap原始碼閱讀HashMap原始碼
- fuzz原始碼閱讀原始碼
- RunLoop 原始碼閱讀OOP原始碼
- express 原始碼閱讀Express原始碼
- muduo原始碼閱讀原始碼
- stack原始碼閱讀原始碼
- AmplifyImpostors原始碼閱讀原始碼
- 【原始碼閱讀】Glide原始碼閱讀之load方法(二)原始碼IDE
- TiDB 原始碼閱讀系列文章(十六)INSERT 語句詳解TiDB原始碼
- JDK原始碼閱讀:Object類閱讀筆記JDK原始碼Object筆記