核心行為
開啟Session校驗調度任務、校驗所有的session、具體的Session自我校驗、關閉Session校驗調度任務
核心類
ValidatingSessionManager、SessionValidationScheduler、ValidatingSession
ValidatingSessionManager的行為
public interface ValidatingSessionManager extends SessionManager { // 校驗所有的Session void validateSessions(); }
SessionValidationScheduler的行為
public interface SessionValidationScheduler { // Session校驗是否處於開啟狀態 boolean isEnabled(); // 開啟Session校驗 void enableSessionValidation(); // 關閉Session校驗 void disableSessionValidation(); }
ValidatingSession的行為
public interface ValidatingSession extends Session { // 校驗是否處於開啟狀態 boolean isValid(); // Session自我校驗 void validate() throws InvalidSessionException; }
校驗過程解析
ValidatingSessionManager開啟Session校驗調度任務 ==》 Session校驗調度任務中使用ValidatingSessionManager校驗所有的Session
==》 ValidatingSessionManager讓其子類獲得所有的Session(基礎Session) ==》 各個基礎Session自我校驗
ValidatingSessionManager開啟Session校驗調度任務
protected SessionValidationScheduler sessionValidationScheduler; public void setSessionValidationScheduler(SessionValidationScheduler sessionValidationScheduler) { this.sessionValidationScheduler = sessionValidationScheduler; } protected synchronized void enableSessionValidation() { SessionValidationScheduler scheduler = getSessionValidationScheduler(); if (scheduler == null) { scheduler = createSessionValidationScheduler(); setSessionValidationScheduler(scheduler); } if (!scheduler.isEnabled()) { if (log.isInfoEnabled()) { log.info("Enabling session validation scheduler..."); } // 開啟Session校驗調度任務 scheduler.enableSessionValidation(); afterSessionValidationEnabled(); } }
Session校驗調度任務中使用ValidatingSessionManager校驗所有的Session
public void run() { if (log.isDebugEnabled()) { log.debug("Executing session validation..."); } long startTime = System.currentTimeMillis(); // Session校驗任務調度時使用ValidatingSessionManager校驗所有的Session this.sessionManager.validateSessions(); long stopTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds."); } }
ValidatingSessionManager讓其子類獲得所有的Session(基礎Session)
protected abstract Collection<Session> getActiveSessions();
DefaultSessionManager具體執行獲得所有的基礎Session
protected Collection<Session> getActiveSessions() { Collection<Session> active = sessionDAO.getActiveSessions(); return active != null ? active : Collections.<Session>emptySet(); }
各個基礎Session自我校驗
Collection<Session> activeSessions = getActiveSessions(); if (activeSessions != null && !activeSessions.isEmpty()) { for (Session s : activeSessions) { try { SessionKey key = new DefaultSessionKey(s.getId()); // 各個基礎Session自我校驗 validate(s, key); } catch (InvalidSessionException e) { if (log.isDebugEnabled()) { boolean expired = (e instanceof ExpiredSessionException); String msg = "Invalidated session with id [" + s.getId() + "]" + (expired ? " (expired)" : " (stopped)"); log.debug(msg); } invalidCount++; } } } protected void validate(Session session, SessionKey key) throws InvalidSessionException { try { doValidate(session); } catch (ExpiredSessionException ese) { onExpiration(session, ese, key); throw ese; } catch (InvalidSessionException ise) { onInvalidation(session, ise, key); throw ise; } } protected void doValidate(Session session) throws InvalidSessionException { if (session instanceof ValidatingSession) { // 基礎Session根據自己擁有的屬性值自我校驗 ((ValidatingSession) session).validate(); } else { String msg = "The " + getClass().getName() + " implementation only supports validating " + "Session implementations of the " + ValidatingSession.class.getName() + " interface. " + "Please either implement this interface in your session implementation or override the " + AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation."; throw new IllegalStateException(msg); } }
SimpleSession的自我校驗
public void validate() throws InvalidSessionException { // 校驗Session是否已經被停止使用了,如果Session已經被停止使用了則拋出異常 if (isStopped()) { String msg = "Session with id [" + getId() + "] has been " + "explicitly stopped. No further interaction under this session is " + "allowed."; throw new StoppedSessionException(msg); } // 校驗Session是否到了過期時間,如果Session已經到期了則拋出異常 if (isTimedOut()) { expire(); Date lastAccessTime = getLastAccessTime(); long timeout = getTimeout(); Serializable sessionId = getId(); DateFormat df = DateFormat.getInstance(); String msg = "Session with id [" + sessionId + "] has expired. " + "Last access time: " + df.format(lastAccessTime) + ". Current time: " + df.format(new Date()) + ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" + timeout / MILLIS_PER_MINUTE + " minutes)"; if (log.isTraceEnabled()) { log.trace(msg); } throw new ExpiredSessionException(msg); } } protected boolean isStopped() { return getStopTimestamp() != null; } protected boolean isTimedOut() { if (isExpired()) { return true; } long timeout = getTimeout(); if (timeout >= 0l) { Date lastAccessTime = getLastAccessTime(); if (lastAccessTime == null) { String msg = "session.lastAccessTime for session with id [" + getId() + "] is null. This value must be set at " + "least once, preferably at least upon instantiation. Please check the " + getClass().getName() + " implementation and ensure " + "this value will be set (perhaps in the constructor?)"; throw new IllegalStateException(msg); } long expireTimeMillis = System.currentTimeMillis() - timeout; Date expireTime = new Date(expireTimeMillis); return lastAccessTime.before(expireTime); } else { if (log.isTraceEnabled()) { log.trace("No timeout for session with id [" + getId() + "]. Session is not considered expired."); } } return false; } public boolean isExpired() { return expired; } protected void expire() { stop(); this.expired = true; } public void stop() { if (this.stopTimestamp == null) { this.stopTimestamp = new Date(); } }
SimpleSession過期后自己無能為力,只能拋出異常交給AbstractValidatingSessionManager抓住異常進行特殊處理
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) { log.trace("Session with id [{}] has expired.", s.getId()); try { // 執行過期時的行為 onExpiration(s); // 通知監聽器,Session過期之后做點什么 notifyExpiration(s); } finally { // Session過期之后的行為,如在介質中刪除Session afterExpired(s); } }
// 更新介質中的Session protected void onExpiration(Session session) { onChange(session); } protected void afterExpired(Session session) { }
ValidatingSessionManager關閉Session校驗調度任務
protected synchronized void disableSessionValidation() { beforeSessionValidationDisabled(); SessionValidationScheduler scheduler = getSessionValidationScheduler(); if (scheduler != null) { try { // Session校驗任務調度器禁用校驗 scheduler.disableSessionValidation(); if (log.isInfoEnabled()) { log.info("Disabled session validation scheduler."); } } catch (Exception e) { if (log.isDebugEnabled()) { String msg = "Unable to disable SessionValidationScheduler. Ignoring (shutting down)..."; log.debug(msg, e); } } LifecycleUtils.destroy(scheduler); // 設置Session校驗任務調度器為 null setSessionValidationScheduler(null); } }
Session任務調度器禁用Session校驗
public void disableSessionValidation() { if (this.service != null) { this.service.shutdownNow(); } this.enabled = false; }