熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

tomcat的session實現原理

2013-11-23 20:34:41  來源: Java開源技術 
    服務器端實現原理
   
    Session在服務器端具體是怎麼實現的呢?我們使用session的時候一般都是這麼使用的requestgetSession()或者requestgetSession(true)
   
    這個時候服務器就檢查是不是已經存在對應的Session對象見HttpRequestBase類
   
    doGetSession(boolean create)方法
   
    if ((session != null) && !sessionisValid())
   
    session = null;
   
    if (session != null)
   
    return (sessiongetSession())
   
   
   
   
   
    // Return the requested session if it exists and is valid
   
    Manager manager = null;
   
    if (context != null)
   
    manager = contextgetManager()
   
    if (manager == null)
   
    return (null) // Sessions are not supported
   
    if (requestedSessionId != null) {
   
    try {
   
    session = managerfindSession(requestedSessionId)
   
    } catch (IOException e) {
   
    session = null;
   
    }
   
    if ((session != null) && !sessionisValid())
   
    session = null;
   
    if (session != null) {
   
    return (sessiongetSession())
   
    }
   
    }
   
    requestSessionId從哪裡來呢?這個肯定是通過Session實現機制的cookie或URL重寫來設置的見HttpProcessor類中的parseHeaders(SocketInputStream input)
   
    for (int i = ; i < cookieslength; i++) {
   
    if (cookies[i]getName()equals
   
    (GlobalsSESSION_COOKIE_NAME)) {
   
    // Override anything requested in the URL
   
    if (!requestisRequestedSessionIdFromCookie()) {
   
    // Accept only the first session id cookie
   
    requestsetRequestedSessionId
   
    (cookies[i]getValue())
   
    requestsetRequestedSessionCookie(true)
   
    requestsetRequestedSessionURL(false)
   
   
   
    }
   
    }
   
    }
   
    或者HttpOrocessor類中的parseRequest(SocketInputStream input OutputStream output)
   
    // Parse any requested session ID out of the request URI
   
    int semicolon = uriindexOf(match) //match 是;jsessionid=字符串
   
    if (semicolon >= ) {
   
    String rest = urisubstring(semicolon + matchlength())
   
    int semicolon = restindexOf(;
   
    if (semicolon >= ) {
   
    requestsetRequestedSessionId(restsubstring( semicolon))
   
    rest = restsubstring(semicolon
   
    } else {
   
    requestsetRequestedSessionId(rest)
   
    rest = ;
   
    }
   
    requestsetRequestedSessionURL(true)
   
    uri = urisubstring( semicolon) + rest;
   
    if (debug >=
   
    log( Requested URL session id is +
   
    ((HttpServletRequest) requestgetRequest())
   
    getRequestedSessionId())
   
    } else {
   
    requestsetRequestedSessionId(null)
   
    requestsetRequestedSessionURL(false)
   
    }
   
   
   
    裡面的managerfindSession(requestSessionId)用於查找此會話ID對應的session對象Tomcat實現是通過一個HashMap實現見ManagerBasejava的findSession(String id)
   
    if (id == null)
   
    return (null)
   
    synchronized (sessions) {
   
    Session session = (Session) sessionsget(id)
   
    return (session)
   
    }
   
    Session本身也是實現為一個HashMap因為Session設計為存放keyvalue鍵值對Tomcat裡面Session實現類是StandardSession裡面一個attributes屬性
   
    /**
   
    * The collection of user data attributes associated with this Session
   
    */
   
    private HashMap attributes = new HashMap()
   
    所有會話信息的存取都是通過這個屬性來實現的Session會話信息不會一直在服務器端保存超過一定的時間期限就會被刪除這個時間期限可以在 webxml中進行設置不設置的話會有一個默認值Tomcat的默認值是那麼服務器端是怎麼判斷會話過期的呢?原理服務器會啟動一個線程一直查詢所有的Session對象檢查不活動的時間是否超過設定值如果超過就將其刪除見StandardManager類它實現了Runnable 接口裡面的run方法如下
   
    /**
   
    * The background thread that checks for session timeouts and shutdown
   
    */
   
    public void run() {
   
   
   
    // Loop until the termination semaphore is set
   
    while (!threadDone) {
   
    threadSleep()
   
    proces***pires()
   
    }
   
   
   
    }
   
   
   
    /**
   
    * Invalidate all sessions that have expired
   
    */
   
    private void proces***pires() {
   
   
   
    long timeNow = SystemcurrentTimeMillis()
   
    Session sessions[] = findSessions()
   
   
   
    for (int i = ; i < sessionslength; i++) {
   
    StandardSession session = (StandardSession) sessions[i];
   
    if (!sessionisValid())
   
    continue;
   
    int maxInactiveInterval = sessiongetMaxInactiveInterval()
   
    if (maxInactiveInterval <
   
    continue;
   
    int timeIdle = // Truncate do not round up
   
    (int) ((timeNow sessiongetLastUsedTime()) / L)
   
    if (timeIdle >= maxInactiveInterval) {
   
    try {
   
    expiredSessions++;
   
    sessionexpire()
   
    } catch (Throwable t) {
   
    log(smgetString(standardManagerexpireException t)
   
    }
   
    }
   
    }
   
   
   
    }
   
    Session 信息在createexpire等事情的時候都會觸發相應的Listener事件從而可以對session信息進行監控這些Listener只需要繼承HttpSessionListener並配置在webxml文件中如下是一個監控在線會話數的Listerner:
   
    import javautilHashSet;
   
    import javaxservletServletContext;
   
    import javaxservlethttpHttpSession;
   
    import javaxservlethttpHttpSessionEvent;
   
    import javaxservlethttpHttpSessionListener;
   
    public class MySessionListener implements HttpSessionListener {
   
    public void sessionCreated(HttpSessionEvent event) {
   
    HttpSession session = eventgetSession()
   
    ServletContext application = sessiongetServletContext()
   
    // 在application范圍由一個HashSet集保存所有的session
   
    HashSet sessions = (HashSet) applicationgetAttribute(sessions
   
    if (sessions == null) {
   
    sessions = new HashSet()
   
    applicationsetAttribute(sessions sessions)
   
    }
   
    // 新創建的session均添加到HashSet集中
   
    sessionsadd(session)
   
    // 可以在別處從application范圍中取出sessions集合
   
    // 然後使用sessionssize()獲取當前活動的session數即為在線人數
   
    }
   
    public void sessionDestroyed(HttpSessionEvent event) {
   
    HttpSession session = eventgetSession()
   
    ServletContext application = sessiongetServletContext()
   
    HashSet sessions = (HashSet) applicationgetAttribute(sessions
   
    // 銷毀的session均從HashSet集中移除
   
    sessionsremove(session)
   
    }
   
    }
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28703.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.