亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

How Tomcat Works(十二)

系統(tǒng) 2044 0

tomcat容器通過一個稱為Session管理器的組件來管理建立的Session對象,該組件由org.apache.catalina.Manager接口表示;Session管理器必須與一個Context容器相關(guān)聯(lián)(需要用到Context容器的相關(guān)上下文或方法)。

默認情況下,Session管理器會將其所管理的 Session對象存放在內(nèi)存中,不過在tomcat中,Session管理器也庫將Session對象持久化,存儲到文件存儲器或通過JDBC寫入到數(shù)據(jù)庫中。

下面我們來分析具體實現(xiàn),在servlet編程方面中,Session對象由javax.servlet.http.HttpSession接口表示;在tomcat中該接口的標準實現(xiàn)是org.apache.catalina.session包下的StandardSession類,該類同時實現(xiàn)了org.apache.catalina.Session接口,在tomcat內(nèi)部供Session管理器使用;而實際交給servlet實例使用的是Session接口的外觀類StandardSessionFacade

下面是Session管理器內(nèi)部使用的Session接口

      
        public
      
      
        interface
      
      
         Session {
    
      
      
        public
      
      
        static
      
      
        final
      
       String SESSION_CREATED_EVENT = "createSession"
      
        ;
   
      
      
        public
      
      
        static
      
      
        final
      
       String SESSION_DESTROYED_EVENT = "destroySession"
      
        ;
   
      
      
        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
      
      
        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);

}
      
    

Session對象總是存在于Session管理器中,可以通過setManager()方法將Session實例 與某個Session管理器相關(guān)聯(lián);Session管理器可以通過setId()方法設(shè)置Session標識符;同時會調(diào)用getLastAccessedTime()方法判斷一個Session對象的有效性;setValid()方法用于重置該Session對象的有效性;每當訪問一個Session實例時,會調(diào)用access()方法來修改Session對象的最后訪問時間;最后,Session管理器會調(diào)用Session對象的expire()方法使其過期,通過getSession()方法獲取一個經(jīng)過外觀類StandardSessionFacade包裝的HttpSession對象

StandardSession類是Session接口的標準實現(xiàn),同時實現(xiàn)了javax.servlet.http.HttpSession接口和java.lang.Serializable接口

(注:StandardSession類實現(xiàn)HttpSession接口方法的實現(xiàn)基本上都依賴于實現(xiàn)Session接口的方法對StandardSession實例的填充,因此我們可以想象,StandardSession類基本上類似與適配器模式中的Adapter角色,實現(xiàn)了原類型(Session接口類型)到目標接口的轉(zhuǎn)換(HttpSession接口))

其構(gòu)造函數(shù)接受一個Manager接口的實例,迫使Session對象必須擁有一個Session管理器實例

      
        public
      
      
         StandardSession(Manager manager) {

        
      
      
        super
      
      
        ();
        
      
      
        this
      
      .manager =
      
         manager;
        
      
      
        if
      
       (manager 
      
        instanceof
      
      
         ManagerBase)
            
      
      
        this
      
      .debug =
      
         ((ManagerBase) manager).getDebug();

    }
      
    

下面是StandardSession實例的一些比較重要的私有成員變量

      
        //
      
      
        存儲session的鍵值對
      
      
        private
      
       HashMap attributes = 
      
        new
      
      
         HashMap();

      
      
        private
      
      
        transient
      
       String authType = 
      
        null
      
      
        ;

      
      
        //
      
      
        創(chuàng)建時間
      
      
        private
      
      
        long
      
       creationTime = 0L
      
        ;

      
      
        //
      
      
        是否過期
      
      
        private
      
      
        transient
      
      
        boolean
      
       expiring = 
      
        false
      
      
        ;

      
      
        //
      
      
        外觀類
      
      
        private
      
      
        transient
      
       StandardSessionFacade facade = 
      
        null
      
      
        ;

      
      
        //
      
      
        session標識
      
      
        private
      
       String id = 
      
        null
      
      
        ;

      
      
        //
      
      
        最后訪問時間
      
      
        private
      
      
        long
      
       lastAccessedTime =
      
         creationTime;

      
      
        //
      
      
        監(jiān)聽器聚集
      
      
        private
      
      
        transient
      
       ArrayList listeners = 
      
        new
      
      
         ArrayList();

      
      
        //
      
      
        session管理器
      
      
        private
      
       Manager manager = 
      
        null
      
      
        ;

      
      
        //
      
      
        清理session過期時間
      
      
        private
      
      
        int
      
       maxInactiveInterval = -1
      
        ;

      
      
        private
      
      
        boolean
      
       isNew = 
      
        false
      
      
        ;

      
      
        private
      
      
        boolean
      
       isValid = 
      
        false
      
      
        ;

      
      
        //
      
      
        當前訪問時間
      
      
        private
      
      
        long
      
       thisAccessedTime = creationTime;
    

其中g(shù)etSession()方法通過傳入自身實例來創(chuàng)建外觀類StandardSessionFacade實例

      
        public
      
      
         HttpSession getSession() {

        
      
      
        if
      
       (facade == 
      
        null
      
      
        )
            facade 
      
      = 
      
        new
      
       StandardSessionFacade(
      
        this
      
      
        );
        
      
      
        return
      
      
         (facade);

    }
      
    

如果session管理器中的某個Session對象在某個時間長度內(nèi)都沒有被訪問的話,會被Session管理器設(shè)置為過期,這個時間長度是由變量maxInactiveInterval的值來指定

      
        public
      
      
        void
      
       expire(
      
        boolean
      
      
         notify) {

        
      
      
        //
      
      
         Mark this session as "being expired" if needed
      
      
        if
      
      
         (expiring)
            
      
      
        return
      
      
        ;
        expiring 
      
      = 
      
        true
      
      
        ;
        setValid(
      
      
        false
      
      
        );

        
      
      
        //
      
      
         Remove this session from our manager's active sessions
      
      
        if
      
       (manager != 
      
        null
      
      
        )
            manager.remove(
      
      
        this
      
      
        );

        
      
      
        //
      
      
         Unbind any objects associated with this session
      
      
        String keys[] =
      
         keys();
        
      
      
        for
      
       (
      
        int
      
       i = 0; i < keys.length; i++
      
        )
            removeAttribute(keys[i], notify);

        
      
      
        //
      
      
         Notify interested session event listeners
      
      
        if
      
      
         (notify) {
            fireSessionEvent(Session.SESSION_DESTROYED_EVENT, 
      
      
        null
      
      
        );
        }

        
      
      
        //
      
      
         Notify interested application event listeners
        
      
      
        //
      
      
         FIXME - Assumes we call listeners in reverse order
      
      
        Context context =
      
         (Context) manager.getContainer();
        Object listeners[] 
      
      =
      
         context.getApplicationListeners();
        
      
      
        if
      
       (notify && (listeners != 
      
        null
      
      
        )) {
            HttpSessionEvent event 
      
      =
              
      
        new
      
      
         HttpSessionEvent(getSession());
            
      
      
        for
      
       (
      
        int
      
       i = 0; i < listeners.length; i++
      
        ) {
                
      
      
        int
      
       j = (listeners.length - 1) -
      
         i;
                
      
      
        if
      
       (!(listeners[j] 
      
        instanceof
      
      
         HttpSessionListener))
                    
      
      
        continue
      
      
        ;
                HttpSessionListener listener 
      
      =
      
        
                    (HttpSessionListener) listeners[j];
                
      
      
        try
      
      
         {
                    fireContainerEvent(context,
                                       
      
      "beforeSessionDestroyed"
      
        ,
                                       listener);
                    listener.sessionDestroyed(event);
                    fireContainerEvent(context,
                                       
      
      "afterSessionDestroyed"
      
        ,
                                       listener);
                } 
      
      
        catch
      
      
         (Throwable t) {
                    
      
      
        try
      
      
         {
                        fireContainerEvent(context,
                                           
      
      "afterSessionDestroyed"
      
        ,
                                           listener);
                    } 
      
      
        catch
      
      
         (Exception e) {
                        ;
                    }
                    
      
      
        //
      
      
         FIXME - should we do anything besides log these?
      
      
                    log(sm.getString("standardSession.sessionEvent"
      
        ), t);
                }
            }
        }

        
      
      
        //
      
      
         We have completed expire of this session
      
      
        expiring = 
      
        false
      
      
        ;
        
      
      
        if
      
       ((manager != 
      
        null
      
      ) && (manager 
      
        instanceof
      
      
         ManagerBase)) {
            recycle();
        }

    }
      
    

上面方法中從Session管理器移除該session實例并觸發(fā)一些事件,同時設(shè)置一些內(nèi)部變量的值。

為了傳遞一個session對象給servlet實例,tomcat的session管理器會實例化StandardSession類,并填充該session對象;不過,為了阻止servlet程序員訪問StandardSession實例中的一些敏感方法,tomcat容器將StandardSession實例封裝為StandardSessionFacade類型的實例(實現(xiàn)HttpRequest接口的HttpRequestBase類的doGetSession方法里面調(diào)用session管理器的createSession()方法返回StandardSession類的實例,然后調(diào)用StandardSession實例 的getSession()方法返回StandardSessionFacade類型實例),該類僅僅實現(xiàn)了javax.servlet.http.HttpSession接口中的方法,這樣servlet程序員就不能將HttpSession對象向下轉(zhuǎn)型為StandardSession類型

下面接下來描述session管理器,session管理器是org.apache.catalina.Manager接口的實例,抽象類ManagerBase實現(xiàn)了Manager接口,提供了常見功能的實現(xiàn);ManagerBase類有兩個直接子類,分別為StandardManager類和PersistentManagerBase類

當tomcat運行時,StandardManager實例將session對象存儲在內(nèi)存中;當tomcat關(guān)閉時,它會將當前內(nèi)存中所有的session對象序列化存儲到文件中;當在此運行tomcat時,又會將這些session對象重新載入內(nèi)存。

另外,繼承自PersistentManagerBase類的session管理器會將session對象存儲到輔助存儲器中,包括PersistentManager類和DistributedManager類(tomcat4中)

下面是Manager接口的方法聲明:

      
        public
      
      
        interface
      
      
         Manager {
    
      
      
        public
      
      
         Container getContainer();
   
      
      
        public
      
      
        void
      
      
         setContainer(Container container);
    
      
      
        public
      
      
         DefaultContext getDefaultContext();
   
      
      
        public
      
      
        void
      
      
         setDefaultContext(DefaultContext defaultContext);
    
      
      
        public
      
      
        boolean
      
      
         getDistributable();
   
      
      
        public
      
      
        void
      
       setDistributable(
      
        boolean
      
      
         distributable);
   
      
      
        public
      
      
         String getInfo();
    
      
      
        public
      
      
        int
      
      
         getMaxInactiveInterval();
    
      
      
        public
      
      
        void
      
       setMaxInactiveInterval(
      
        int
      
      
         interval);
   
      
      
        public
      
      
        void
      
      
         add(Session session);
   
      
      
        public
      
      
        void
      
      
         addPropertyChangeListener(PropertyChangeListener listener);
    
      
      
        public
      
      
         Session createSession();
    
      
      
        public
      
       Session findSession(String id) 
      
        throws
      
      
         IOException;
   
      
      
        public
      
      
         Session[] findSessions();
   
      
      
        public
      
      
        void
      
       load() 
      
        throws
      
      
         ClassNotFoundException, IOException;
   
      
      
        public
      
      
        void
      
      
         remove(Session session);
   
      
      
        public
      
      
        void
      
      
         removePropertyChangeListener(PropertyChangeListener listener);
   
      
      
        public
      
      
        void
      
       unload() 
      
        throws
      
      
         IOException;

}
      
    

提供了setContainer()方法使用session管理器與Context容器相關(guān)聯(lián);一起一下添加、移除session實例的方法;設(shè)置session對象的最長存活時間;最后, load()方法與unload()方法用于從輔助存儲器加載session對象到內(nèi)存和序列化session對象并持久化到輔助存儲器中。

ManagerBase類為一個抽象類,提供了一些公共方法的實現(xiàn),包括創(chuàng)建session對象、移除session對象等;這些活動的session對象都存儲在一個名為sessions的HashMap變量中

protected HashMap sessions = new HashMap();

下面是創(chuàng)建session實例的方法

      
        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);

    }
      
    

上面創(chuàng)建的是StandardSession類型實例,在實現(xiàn)HttpRequest接口的HttpRequestBase類的相關(guān)方法中,調(diào)用getSession()方法返回StandardSessionFacade類型實例

創(chuàng)建session對象需要調(diào)用受保護的方法返回session對象的唯一標識符

      
        /**
      
      
        
     * Generate and return a new session identifier.
     
      
      
        */
      
      
        protected
      
      
        synchronized
      
      
         String generateSessionId() {

        
      
      
        //
      
      
         Generate a byte array containing a session identifier
      
      
        Random random =
      
         getRandom();
        
      
      
        byte
      
       bytes[] = 
      
        new
      
      
        byte
      
      
        [SESSION_ID_BYTES];
        getRandom().nextBytes(bytes);
        bytes 
      
      =
      
         getDigest().digest(bytes);

        
      
      
        //
      
      
         Render the result as a String of hexadecimal digits
      
      
        StringBuffer result = 
      
        new
      
      
         StringBuffer();
        
      
      
        for
      
       (
      
        int
      
       i = 0; i < bytes.length; i++
      
        ) {
            
      
      
        byte
      
       b1 = (
      
        byte
      
      ) ((bytes[i] & 0xf0) >> 4
      
        );
            
      
      
        byte
      
       b2 = (
      
        byte
      
      ) (bytes[i] & 0x0f
      
        );
            
      
      
        if
      
       (b1 < 10
      
        )
                result.append((
      
      
        char
      
      ) ('0' +
      
         b1));
            
      
      
        else
      
      
        
                result.append((
      
      
        char
      
      ) ('A' + (b1 - 10
      
        )));
            
      
      
        if
      
       (b2 < 10
      
        )
                result.append((
      
      
        char
      
      ) ('0' +
      
         b2));
            
      
      
        else
      
      
        
                result.append((
      
      
        char
      
      ) ('A' + (b2 - 10
      
        )));
        }
        
      
      
        return
      
      
         (result.toString());

    }
      
    

該標識符生成之后,會發(fā)送到客戶端cookies里面,使客戶端cookies里面的 JSESSIONID 值與之一致

其他相關(guān)操作session對象方法如下,容易理解

      
        public
      
      
        void
      
      
         add(Session session) {

        
      
      
        synchronized
      
      
         (sessions) {
            sessions.put(session.getId(), session);
        }

    }

    
      
      
        public
      
       Session findSession(String id) 
      
        throws
      
      
         IOException {

        
      
      
        if
      
       (id == 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        null
      
      
        );
        
      
      
        synchronized
      
      
         (sessions) {
            Session session 
      
      =
      
         (Session) sessions.get(id);
            
      
      
        return
      
      
         (session);
        }

    }
    
      
      
        public
      
      
         Session[] findSessions() {

        Session results[] 
      
      = 
      
        null
      
      
        ;
        
      
      
        synchronized
      
      
         (sessions) {
            results 
      
      = 
      
        new
      
      
         Session[sessions.size()];
            results 
      
      =
      
         (Session[]) sessions.values().toArray(results);
        }
        
      
      
        return
      
      
         (results);

    }
   
      
      
        public
      
      
        void
      
      
         remove(Session session) {

        
      
      
        synchronized
      
      
         (sessions) {
            sessions.remove(session.getId());
        }

    }
      
    

StandardManager類是Manager接口的標準實現(xiàn),繼承自上面的ManagerBase抽象類,同時實現(xiàn)了Lifecycle接口,這有可以由其相關(guān)聯(lián)的Context容器來啟動和關(guān)閉,在Context容器調(diào)用它的start()方法和stop()方法時,會調(diào)用load()從輔助存儲器加載session對象到內(nèi)存和調(diào)用unload()方法從內(nèi)存持久化session對象到輔助存儲器

同時session管理器還負責銷毀那些失效的session對象,這是由一個專門的線程來實現(xiàn)的,StandardManager類實現(xiàn)了Runnable接口

      
        /**
      
      
        
     * The background thread that checks for session timeouts and shutdown.
     
      
      
        */
      
      
        public
      
      
        void
      
      
         run() {

        
      
      
        //
      
      
         Loop until the termination semaphore is set
      
      
        while
      
       (!
      
        threadDone) {
            threadSleep();
            processExpires();
        }

    }
      
    

在線程休眠指定時間間隔后,調(diào)用processExpires()方法清理過期session對象

      
        /**
      
      
        
     * Invalidate all sessions that have expired.
     
      
      
        */
      
      
        private
      
      
        void
      
      
         processExpires() {

        
      
      
        long
      
       timeNow =
      
         System.currentTimeMillis();
        Session sessions[] 
      
      =
      
         findSessions();

        
      
      
        for
      
       (
      
        int
      
       i = 0; i < sessions.length; i++
      
        ) {
            StandardSession session 
      
      =
      
         (StandardSession) sessions[i];
            
      
      
        if
      
       (!
      
        session.isValid())
                
      
      
        continue
      
      
        ;
            
      
      
        int
      
       maxInactiveInterval =
      
         session.getMaxInactiveInterval();
            
      
      
        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);
                }
            }
        }

    }
      
    

我們可以看到,session對象的過期時間實際是session對象本身的成員變量的值

int maxInactiveInterval = session.getMaxInactiveInterval()

最后,servlet程序員需要調(diào)用javax.servlet.http.HttpSerletRequest接口的getSession()方法獲取Session對象,當調(diào)用getSession()方法時,request對象必須調(diào)用與Context容器相關(guān)聯(lián)的session管理器(創(chuàng)建session對象或返回一個已存在色session對象);request對象為了能夠訪問Session管理器,它必須能夠訪問Context容器。因此在SimpleWrapperValve類的invoke()方法中,需要調(diào)用org.apache.catalina.Request接口的setContext()方法傳入Context容器實例

      
        public
      
      
        void
      
      
         invoke(Request request, Response response, ValveContext valveContext)
    
      
      
        throws
      
      
         IOException, ServletException {

    SimpleWrapper wrapper 
      
      =
      
         (SimpleWrapper) getContainer();
    ServletRequest sreq 
      
      =
      
         request.getRequest();
    ServletResponse sres 
      
      =
      
         response.getResponse();
    Servlet servlet 
      
      = 
      
        null
      
      
        ;
    HttpServletRequest hreq 
      
      = 
      
        null
      
      
        ;
    
      
      
        if
      
       (sreq 
      
        instanceof
      
      
         HttpServletRequest)
      hreq 
      
      =
      
         (HttpServletRequest) sreq;
    HttpServletResponse hres 
      
      = 
      
        null
      
      
        ;
    
      
      
        if
      
       (sres 
      
        instanceof
      
      
         HttpServletResponse)
      hres 
      
      =
      
         (HttpServletResponse) sres;

    
      
      
        //
      
      
        -- new addition -----------------------------------
      
      
        Context context = (Context) wrapper.getParent();
    request.setContext(context);
    
      
      
        //
      
      
        -------------------------------------
    
      
      
        //
      
      
         Allocate a servlet instance to process this request
      
      
        try
      
      
         {
      servlet 
      
      =
      
         wrapper.allocate();
      
      
      
        if
      
       (hres!=
      
        null
      
       && hreq!=
      
        null
      
      
        ) {
        servlet.service(hreq, hres);
      }
      
      
      
        else
      
      
         {
        servlet.service(sreq, sres);
      }
    }
    
      
      
        catch
      
      
         (ServletException e) {
    }
  }
      
    

同時在org.apache.catalina.connector.HttpRequestBase類的私有方法diGetSession()里面會調(diào)用Context接口的getManager()方法來獲取session管理器對象

      
        private
      
       HttpSession doGetSession(
      
        boolean
      
      
         create) {
        
      
      
        //
      
      
         There cannot be a session if no context has been assigned yet
      
      
        if
      
       (context == 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        null
      
      
        );

        
      
      
        //
      
      
         Return the current session if it exists and is valid
      
      
        if
      
       ((session != 
      
        null
      
      ) && !
      
        session.isValid())
            session 
      
      = 
      
        null
      
      
        ;
        
      
      
        if
      
       (session != 
      
        null
      
      
        )
            
      
      
        return
      
      
         (session.getSession());


        
      
      
        //
      
      
         Return the requested session if it exists and is valid
      
      
        Manager manager = 
      
        null
      
      
        ;
        
      
      
        if
      
       (context != 
      
        null
      
      
        )
            manager 
      
      =
      
         context.getManager();

        
      
      
        if
      
       (manager == 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        null
      
      );      
      
        //
      
      
         Sessions are not supported
      
      
        if
      
       (requestedSessionId != 
      
        null
      
      
        ) {
            
      
      
        try
      
      
         {
                session 
      
      =
      
         manager.findSession(requestedSessionId);
            } 
      
      
        catch
      
      
         (IOException e) {
                session 
      
      = 
      
        null
      
      
        ;
            }
            
      
      
        if
      
       ((session != 
      
        null
      
      ) && !
      
        session.isValid())
                session 
      
      = 
      
        null
      
      
        ;
            
      
      
        if
      
       (session != 
      
        null
      
      
        ) {
                
      
      
        return
      
      
         (session.getSession());
            }
        }

        
      
      
        //
      
      
         Create a new session if requested and the response is not committed
      
      
        if
      
       (!
      
        create)
            
      
      
        return
      
       (
      
        null
      
      
        );
        
      
      
        if
      
       ((context != 
      
        null
      
      ) && (response != 
      
        null
      
      ) &&
      
        
            context.getCookies() 
      
      &&
      
        
            response.getResponse().isCommitted()) {
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
              (sm.getString(
      
      "httpRequestBase.createCommitted"
      
        ));
        }

        session 
      
      =
      
         manager.createSession();
        
      
      
        if
      
       (session != 
      
        null
      
      
        )
            
      
      
        return
      
      
         (session.getSession());
        
      
      
        else
      
      
        return
      
       (
      
        null
      
      
        );

    }
      
    

注意里面實質(zhì)是通過StandardSession實例的getSession()方法獲取一個經(jīng)過外觀類StandardSessionFacade包裝的HttpSession對象

---------------------------------------------------------------------------?

本系列How Tomcat Works系本人原創(chuàng)?

轉(zhuǎn)載請注明出處 博客園 刺猬的溫馴?

本人郵箱: ? chenying998179 # 163.com ( #改為@

本文鏈接 http://www.cnblogs.com/chenying99/p/3237390.html

How Tomcat Works(十二)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日本一区视频在线 | 欧洲亚洲精品 | 久久www免费人成_看片美女图 | 国产伦精品一区二区三区四区 | 欧美乱子伦一区二区三区 | 天天干夜夜草 | 牛牛精品| 在线观看国产精品日本不卡网 | 四虎免费影院4hu永久免费 | 一二三区在线观看 | 最新九九精品 | 最新地址四虎www4hutv | 国产99在线视频 | 亚洲国产最新在线一区二区 | 久久久久久麻豆 | 在线亚洲观看 | 国产精品不卡在线 | 黄页成人免费网站 | 免费真实播放国产乱子伦 | 亚洲精品丝袜在线一区波多野结衣 | 久久综合九色综合狠狠97 | 国产成人精品一区二区三区 | 色老头成人免费视频天天综合 | 久re这里只有精品最新地址 | 四虎影永久地址www 四虎影永久在线高清免费 四虎影永久在线观看精品 四虎影永久在线观看网址 四虎影院.com | 99视频观看 | 久久久久日韩精品无 | 九九热思思 | 久久伊人热 | 国产精品久久久久影院色老大 | 日韩日b | 未成人做爰视频www 我爱52avαv永久网站 | 国产精品柳州莫菁身材四 | 日韩欧美一区二区三区不卡 | 香蕉eeww99国产在线观看 | 久久精品国产精品青草不卡 | 色婷婷综合在线视频最新 | 美国一级毛片片aa久久综合 | 精品久久久久久中文字幕无碍 | 91亚洲影院| 看一级特黄a大片日本片 |