tomcat源码解析--Session

tomcat 如何管理 session 相关的数据 及 session的使用

1. 见tomcat中相关session接口的实现


session 接口: 主要包含一些session的常用 功能的方法定义, 包括:

setId/getId sessionID操作

getLastAccessedTime/access 最后访问时间操作

setMaxInactiveInterval/getMaxInactiveInterval  访问最大间隔

expire  过期操作

等等

HttpSession 接口 则是在 javax.servlet.http 包中的

包含了一些J2EE定义的session规则方法,如

getId

getLastAccessedTime

getServletContext 得到javax.servlet.ServletContext

getMaxInactiveInterval

getAttribute

等等

StandardSession是在tomcat org.apache.catalina.session 包中实现上面两个接口的实体类

关联了一个Manager (session管理器)之后讲

关联了一个sessionFacade 作为session的门面

然后定义了session 处理中的一些默认常量

getSession 方法

 public HttpSession getSession() {

        if (facade == null){
            if (SecurityUtil.isPackageProtectionEnabled()){
                final StandardSession fsession = this;
                facade = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction(){
                    public Object run(){
                        return new StandardSessionFacade(fsession);
                    }
                });
            } else {
                facade = new StandardSessionFacade(this);
            }
        }
        return (facade);

    }

 主要就是返回当前StandardSession的facade

isValid 方法,验证是否有效

public boolean isValid() {

        if (this.expiring) {
            return true;
        }

        if (!this.isValid) {
            return false;
        }

        if (ACTIVITY_CHECK && accessCount.get() > 0) {
            return true;
        }

        if (maxInactiveInterval >= 0) { 
            long timeNow = System.currentTimeMillis();
            int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
            if (timeIdle >= maxInactiveInterval) {
                expire(true);
            }
        }

        return (this.isValid);
    }

expire方法

先设置classloader, 然后 发起事件

 expiring = true;
        
            // Notify interested application event listeners
            // FIXME - Assumes we call listeners in reverse order
            Context context = (Context) manager.getContainer();
            
            // The call to expire() may not have been triggered by the webapp.
            // Make sure the webapp's class loader is set when calling the
            // listeners
            ClassLoader oldTccl = null;
            if (context.getLoader() != null &&
                    context.getLoader().getClassLoader() != null) {
                oldTccl = Thread.currentThread().getContextClassLoader();
                if (Globals.IS_SECURITY_ENABLED) {
                    PrivilegedAction<Void> pa = new PrivilegedSetTccl(
                            context.getLoader().getClassLoader());
                    AccessController.doPrivileged(pa);
                } else {
                    Thread.currentThread().setContextClassLoader(
                            context.getLoader().getClassLoader());
                }
            }
            try {
                Object listeners[] = context.getApplicationLifecycleListeners();
                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) {
                                // Ignore
                            }
                            manager.getContainer().getLogger().error
                                (sm.getString("standardSession.sessionEvent"), t);
                        }
                    }
                }

 然后交由session管理器,处理相关操作

session销毁

退出登录

移除相关session的key

long timeNow = System.currentTimeMillis();
            int timeAlive = (int) ((timeNow - creationTime)/1000);
            synchronized (manager) {
                if (timeAlive > manager.getSessionMaxAliveTime()) {
                    manager.setSessionMaxAliveTime(timeAlive);
                }
                int numExpired = manager.getExpiredSessions();
                if (numExpired < Integer.MAX_VALUE) {
                    numExpired++;
                    manager.setExpiredSessions(numExpired);
                }

                int average = manager.getSessionAverageAliveTime();
                // Using long, as otherwise (average * numExpired) might overflow 
                average = (int) (((((long) average) * (numExpired - 1)) + timeAlive)
                        / numExpired);
                manager.setSessionAverageAliveTime(average);
            }

            if (manager instanceof ManagerBase) {
                ManagerBase mb = (ManagerBase) manager;
                SessionTiming timing = new SessionTiming(timeNow, timeAlive);
                synchronized (mb.sessionExpirationTiming) {
                    mb.sessionExpirationTiming.add(timing);
                    mb.sessionExpirationTiming.poll();
                }
            }

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

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

            // Call the logout method
            if (principal instanceof GenericPrincipal) {
                GenericPrincipal gp = (GenericPrincipal) principal;
                try {
                    gp.logout();
                } catch (Exception e) {
                    manager.getContainer().getLogger().error(
                            sm.getString("standardSession.logoutfail"),
                            e);
                }
            }

            // We have completed expire of this session
            expiring = false;

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

readObject 读取 流, 初始化session (读取session文件初始化session)

 authType = null;        // Transient only
        creationTime = ((Long) stream.readObject()).longValue();
        lastAccessedTime = ((Long) stream.readObject()).longValue();
        maxInactiveInterval = ((Integer) stream.readObject()).intValue();
        isNew = ((Boolean) stream.readObject()).booleanValue();
        isValid = ((Boolean) stream.readObject()).booleanValue();
        thisAccessedTime = ((Long) stream.readObject()).longValue();
        principal = null;        // Transient only
        //        setId((String) stream.readObject());
        id = (String) stream.readObject();
        if (manager.getContainer().getLogger().isDebugEnabled())
            manager.getContainer().getLogger().debug
                ("readObject() loading session " + id);

        // Deserialize the attribute count and attribute values
        if (attributes == null)
            attributes = new Hashtable();
        int n = ((Integer) stream.readObject()).intValue();
        boolean isValidSave = isValid;
        isValid = true;
        for (int i = 0; i < n; i++) {
            String name = (String) stream.readObject();
            Object value = (Object) stream.readObject();
            if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
                continue;
            if (manager.getContainer().getLogger().isDebugEnabled())
                manager.getContainer().getLogger().debug("  loading attribute '" + name +
                    "' with value '" + value + "'");
            attributes.put(name, value);
        }
        isValid = isValidSave;

        if (listeners == null) {
            listeners = new ArrayList();
        }

        if (notes == null) {
            notes = new Hashtable();
        }

writeObject 写出到流

 stream.writeObject(new Long(creationTime));
        stream.writeObject(new Long(lastAccessedTime));
        stream.writeObject(new Integer(maxInactiveInterval));
        stream.writeObject(new Boolean(isNew));
        stream.writeObject(new Boolean(isValid));
        stream.writeObject(new Long(thisAccessedTime));
        stream.writeObject(id);
        if (manager.getContainer().getLogger().isDebugEnabled())
            manager.getContainer().getLogger().debug
                ("writeObject() storing session " + id);

        // Accumulate the names of serializable and non-serializable attributes
        String keys[] = keys();
        ArrayList saveNames = new ArrayList();
        ArrayList saveValues = new ArrayList();
        for (int i = 0; i < keys.length; i++) {
            Object value = attributes.get(keys[i]);
            if (value == null)
                continue;
            else if ( (value instanceof Serializable) 
                    && (!exclude(keys[i]) )) {
                saveNames.add(keys[i]);
                saveValues.add(value);
            } else {
                removeAttributeInternal(keys[i], true);
            }
        }

        // Serialize the attribute count and the Serializable attributes
        int n = saveNames.size();
        stream.writeObject(new Integer(n));
        for (int i = 0; i < n; i++) {
            stream.writeObject((String) saveNames.get(i));
            try {
                stream.writeObject(saveValues.get(i));
                if (manager.getContainer().getLogger().isDebugEnabled())
                    manager.getContainer().getLogger().debug
                        ("  storing attribute '" + saveNames.get(i) +
                        "' with value '" + saveValues.get(i) + "'");
            } catch (NotSerializableException e) {
                manager.getContainer().getLogger().warn
                    (sm.getString("standardSession.notSerializable",
                     saveNames.get(i), id), e);
                stream.writeObject(NOT_SERIALIZED);
                if (manager.getContainer().getLogger().isDebugEnabled())
                    manager.getContainer().getLogger().debug
                       ("  storing attribute '" + saveNames.get(i) +
                        "' with value NOT_SERIALIZED");
            }
        }

猜你喜欢

转载自patrick002.iteye.com/blog/2147222