servlet解析演进(7)-session(1)

session是web项目中重要的概念。servlet请求通过session、request等对象保存不同生命周期的数据。

1、session类


servlet解析过程中会涉及到以下几类session信息

servlet解析演进(7)-session(1)_第1张图片

StandardSessionFacede被包含在StandardSession中,作为对外暴漏的门面,既能够为servlet展示需要的方法,又屏蔽了一些StandardSession中一些不想暴库的方法。

//session接口的标准实现。这个对象实现了serializable接口,所以他能够在不同的jvm中存储和传输
//session信息,实现了对分布式session的支持
//类实例代表着内部级别和应用级别的session展示。然而因为这个类本身没有被生命为public,
// 所以org.apache.catalina.session 包外的java逻辑不能讲httpSession实例返回给Session
//如果你为这个类增加属性,你必须确保这个属性覆盖了read/writeObject 方法,以便这个类能够被
//正确的序列化。
class StandardSession
    implements HttpSession, Session, Serializable {
    //session关联的管理器manager
    public StandardSession(Manager manager) {
        super();
        this.manager = manager;
        if (manager instanceof ManagerBase)
            this.debug = ((ManagerBase) manager).getDebug();
    }
//无法序列化时抛出的错误信息
    private static final String NOT_SERIALIZED =
        "___NOT_SERIALIZABLE_EXCEPTION___";
//属性容器
    private HashMap attributes = new HashMap();
//认证类型
    private transient String authType = null;
    /**
     * The <code>java.lang.Method</code> for the
     * <code>fireContainerEvent()</code> method of the
     * <code>org.apache.catalina.core.StandardContext</code> method,
     * if our Context implementation is of this class.  This value is
     * computed dynamically the first time it is needed, or after
     * a session reload (since it is declared transient).
     */
    private transient Method containerEventMethod = null;
    /**
     * The method signature for the <code>fireContainerEvent</code> method.
     */
    private static final Class containerEventTypes[] =
    { String.class, Object.class };
     //session创建时间
    private long creationTime = 0L;
     //debug级别
    private transient int debug = 0;
    //过期时间
    private transient boolean expiring = false;
//该类的门面实例
    private transient StandardSessionFacade facade = null;
//唯一标示
    private String id = null;
//类描述信息
    private static final String info = "StandardSession/1.0";
//最后一次访问时间,初始化为创建时间
    private long lastAccessedTime = creationTime;
//session的监听器链表
    private transient ArrayList listeners = new ArrayList();
//session管理器
    private Manager manager = null;
//session访问的最大间隔时间,如果超过该时间会该session会置为过期。如果是负数,则表示session永不过期
    private int maxInactiveInterval = -1;
//标示session是新旧
    private boolean isNew = false;
//session是否有效
    private boolean isValid = false;
//关联该session的内部注释
    private transient HashMap notes = new HashMap();
//关联该session的授权原则
    private transient Principal principal = null;
//包描述信息
     private static StringManager sm =
        StringManager.getManager(Constants.Package);
//session关联的http session上下文
    private static HttpSessionContext sessionContext = null;
//该容器的属性变更(不能序列化)
    /**
     * The property change support for this component.  NOTE:  This value
     * is not included in the serialized version of this object.
     */
    private transient PropertyChangeSupport support =
        new PropertyChangeSupport(this);
//当前访问时间
    private long thisAccessedTime = creationTime;
    public String getAuthType() {
        return (this.authType);
    }
    public void setAuthType(String authType) {
        String oldAuthType = this.authType;
        this.authType = authType;
        //如果authType属性有变化会触发属性变更监听
        support.firePropertyChange("authType", oldAuthType, this.authType);
    }
    //设置当前时间为创建时间、最后访问时间、当前访问时间
    public void setCreationTime(long time) {
        this.creationTime = time;
        this.lastAccessedTime = time;
        this.thisAccessedTime = time;
    }
    public String getId() {
        return (this.id);
    }
    public void setId(String id) {
        if ((this.id != null) && (manager != null))
            manager.remove(this);
         //设置id
        this.id = id;
      //管理器管理当前类的门面类。
        if (manager != null)
            manager.add(this);
      //触发session监听事件
        // Notify interested session event listeners
        fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
        // 获取容器上下文。
        Context context = (Context) manager.getContainer();
        //监听器数组
        Object listeners[] = context.getApplicationListeners();
        if (listeners != null) {
            HttpSessionEvent event =
                new HttpSessionEvent(getSession());
            for (int i = 0; i < listeners.length; i++) {
                if (!(listeners[i] instanceof HttpSessionListener))
                    continue;
                HttpSessionListener listener =
                    (HttpSessionListener) listeners[i];
                try {
                    fireContainerEvent(context,
                                       "beforeSessionCreated",
                                       listener);
                    //创建session事件
                    listener.sessionCreated(event);
                    fireContainerEvent(context,
                                       "afterSessionCreated",
                                       listener);
                } catch (Throwable t) {
                    try {
                        fireContainerEvent(context,
                                           "afterSessionCreated",
                                           listener);
                    } catch (Exception e) {
                        ;
                    }
                    // FIXME - should we do anything besides log these?
                    log(sm.getString("standardSession.sessionEvent"), t);
                }
            }
        }
    }
    public String getInfo() {
        return (this.info);
    }
    public long getLastAccessedTime() {
        return (this.lastAccessedTime);
    }
    public Manager getManager() {
        return (this.manager);
    }
    public void setManager(Manager manager) {
        this.manager = manager;
    }
    public int getMaxInactiveInterval() {
        return (this.maxInactiveInterval);
    }
    public void setMaxInactiveInterval(int interval) {
        this.maxInactiveInterval = interval;
    }
    public void setNew(boolean isNew) {
        this.isNew = isNew;
    }
    public Principal getPrincipal() {
        return (this.principal);
    }
    public void setPrincipal(Principal principal) {
        Principal oldPrincipal = this.principal;
        this.principal = principal;
        support.firePropertyChange("principal", oldPrincipal, this.principal);
    }
//返回该类的session门面
    public HttpSession getSession() {
        if (facade == null)
            facade = new StandardSessionFacade(this);
        return (facade);
    }
//是否合法
    public boolean isValid() {
        return (this.isValid);
    }
    public void setValid(boolean isValid) {
        this.isValid = isValid;
    }
//访问
    public void access() {
        this.isNew = false;
        this.lastAccessedTime = this.thisAccessedTime;
        this.thisAccessedTime = System.currentTimeMillis();
 }
//添加监听器
    public void addSessionListener(SessionListener listener) {
        synchronized (listeners) {
            listeners.add(listener);
        }
    }
//是否过期
    public void expire() {
        expire(true);
    }
//过期session实例
    public void expire(boolean notify) {
        // Mark this session as "being expired" if needed
        if (expiring)
            return;
        //标示是否正在做过期动作,如果正在做为true
        expiring = true;
        setValid(false);
        // Remove this session from our manager's active sessions
        if (manager != null)
            //删除该session实例
            manager.remove(this);
        //删除属性
        String keys[] = keys();
        for (int i = 0; i < keys.length; i++)
            removeAttribute(keys[i], notify);
        //触发session销毁事件
        if (notify) {
            fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
        }
//返回上下文
        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);
                    //销毁session
                    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);
                }
            }
        }
        // 销毁session过程执行完毕
        expiring = false;
        if ((manager != null) && (manager instanceof ManagerBase)) {
            recycle();
        }
    }
//将session置为非活跃
    public void passivate() {
        // 发送监听消息,触发session非活跃事件
        HttpSessionEvent event = null;
        String keys[] = keys();
        for (int i = 0; i < keys.length; i++) {
            Object attribute = getAttribute(keys[i]);
            if (attribute instanceof HttpSessionActivationListener) {
                if (event == null)
                    event = new HttpSessionEvent(this);
                // FIXME: Should we catch throwables?
                ((HttpSessionActivationListener)attribute).sessionWillPassivate(event);
            }
        }
    }
    //激活session
    public void activate() {
        // Notify ActivationListeners
        //触发session激活事件感兴趣的监听器,触发监听事件。
        HttpSessionEvent event = null;
        String keys[] = keys();
        for (int i = 0; i < keys.length; i++) {
            Object attribute = getAttribute(keys[i]);
            if (attribute instanceof HttpSessionActivationListener) {
                if (event == null)
                    event = new HttpSessionEvent(this);
                // FIXME: Should we catch throwables?
                ((HttpSessionActivationListener)attribute).sessionDidActivate(event);
            }
        }
    }
//返回内部制定名称的note信息
    public Object getNote(String name) {
        synchronized (notes) {
            return (notes.get(name));
        }
    }
    public Iterator getNoteNames() {
        synchronized (notes) {
            return (notes.keySet().iterator());
        }
    }
    /**
     *递归清除所有属性值,并恢复为初始值
     */
    public void recycle() {
         attributes.clear();
        setAuthType(null);
        creationTime = 0L;
        expiring = false;
        id = null;
        lastAccessedTime = 0L;
        maxInactiveInterval = -1;
        notes.clear();
        setPrincipal(null);
        isNew = false;
        isValid = false;
        Manager savedManager = manager;
        manager = null;
        // Tell our Manager that this Session has been recycled
        if ((savedManager != null) && (savedManager instanceof ManagerBase))
            ((ManagerBase) savedManager).recycle(this);
    }
//删除note
    public void removeNote(String name) {
        synchronized (notes) {
            notes.remove(name);
        }
    }
//删除session监听
    public void removeSessionListener(SessionListener listener) {
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }
//绑定对象到制定的名称上
    public void setNote(String name, Object value) {
        synchronized (notes) {
            notes.put(name, value);
        }
    }
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("StandardSession[");
        sb.append(id);
        sb.append("]");
        return (sb.toString());
    }
    //从特定的输入流读数据
    void readObjectData(ObjectInputStream stream)
        throws ClassNotFoundException, IOException {
        readObject(stream);
    }
    //序列化session对象输出端到stream中
    void writeObjectData(ObjectOutputStream stream)
        throws IOException {
        writeObject(stream);
    }
    public long getCreationTime() {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.getCreationTime.ise"));
        return (this.creationTime);
    }
    /**
     * Return the ServletContext to which this session belongs.
     */
    //返回和session关联的容器(上下文)
    public ServletContext getServletContext() {
        if (manager == null)
            return (null);
        Context context = (Context) manager.getContainer();
        if (context == null)
            return (null);
        else
            return (context.getServletContext());
    }
//获得session 关联的session上下文信息
    public HttpSessionContext getSessionContext() {
        if (sessionContext == null)
            sessionContext = new StandardSessionContext();
        return (sessionContext);
    }
//获得属性名称
    public Object getAttribute(String name) {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.getAttribute.ise"));
        synchronized (attributes) {
            return (attributes.get(name));
        }
    }
//获取属性的key值
    public Enumeration getAttributeNames() {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.getAttributeNames.ise"));
        synchronized (attributes) {
            return (new Enumerator(attributes.keySet()));
        }
    }
    public Object getValue(String name) {
        return (getAttribute(name));
    }
    public String[] getValueNames() {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.getValueNames.ise"));
        return (keys());
    }
//将session实例设置为非法,解绑所有绑定在她上线的对象
    public void invalidate() {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.invalidate.ise"));
        // Cause this session to expire
        expire();
    }
    public boolean isNew() {
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.isNew.ise"));
        return (this.isNew);
    }
    public void putValue(String name, Object value) {
        setAttribute(name, value);
    }
    public void removeAttribute(String name) {
        removeAttribute(name, true);
    }
//移除指定名称上绑定的属性对象
    public void removeAttribute(String name, boolean notify) {
        // Validate our current state
        if (!expiring && !isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.removeAttribute.ise"));
        // Remove this attribute from our collection
        Object value = null;
        boolean found = false;
        synchronized (attributes) {
            found = attributes.containsKey(name);
            if (found) {
                value = attributes.get(name);
                attributes.remove(name);
            } else {
                return;
            }
        }
      //是否触发value解绑和属性移除操作
        if (!notify) {
            return;
        }
        //调用 valueUnbound()方法
        HttpSessionBindingEvent event =
          new HttpSessionBindingEvent((HttpSession) this, name, value);
        if ((value != null) &&
            (value instanceof HttpSessionBindingListener))
            ((HttpSessionBindingListener) value).valueUnbound(event);
       //通知感兴趣的事件监听
        Context context = (Context) manager.getContainer();
        Object listeners[] = context.getApplicationListeners();
        if (listeners == null)
            return;
        for (int i = 0; i < listeners.length; i++) {
            if (!(listeners[i] instanceof HttpSessionAttributeListener))
                continue;
            HttpSessionAttributeListener listener =
                (HttpSessionAttributeListener) listeners[i];
            try {
                fireContainerEvent(context,
                                   "beforeSessionAttributeRemoved",
                                   listener);
                //移除属性
                listener.attributeRemoved(event);
                fireContainerEvent(context,
                                   "afterSessionAttributeRemoved",
                                   listener);
            } catch (Throwable t) {
                try {
                    fireContainerEvent(context,
                                       "afterSessionAttributeRemoved",
                                       listener);
                } catch (Exception e) {
                    ;
                }
                // FIXME - should we do anything besides log these?
                log(sm.getString("standardSession.attributeEvent"), t);
            }
        }
    }
//移除某名称的值
    public void removeValue(String name) {
        removeAttribute(name);
    }
 //为属性数组添加key,value
    public void setAttribute(String name, Object value) {
        // Name cannot be null
        if (name == null)
            throw new IllegalArgumentException
                (sm.getString("standardSession.setAttribute.namenull"));
        // Null value is the same as removeAttribute()
        if (value == null) {
            removeAttribute(name);
            return;
        }
        // Validate our current state
        if (!isValid)
            throw new IllegalStateException
                (sm.getString("standardSession.setAttribute.ise"));
        if ((manager != null) && manager.getDistributable() &&
          !(value instanceof Serializable))
            throw new IllegalArgumentException
                (sm.getString("standardSession.setAttribute.iae"));
        // Replace or add this attribute
        Object unbound = null;
        synchronized (attributes) {
            unbound = attributes.get(name);
            attributes.put(name, value);
        }
        // 触发HttpSessionBindingListener监听
        if ((unbound != null) &&
            (unbound instanceof HttpSessionBindingListener)) {
            ((HttpSessionBindingListener) unbound).valueUnbound
              (new HttpSessionBindingEvent((HttpSession) this, name));
        }
        // Call the valueBound() method if necessary
        HttpSessionBindingEvent event = null;
        if (unbound != null)
            event = new HttpSessionBindingEvent
                ((HttpSession) this, name, unbound);
        else
            event = new HttpSessionBindingEvent
                ((HttpSession) this, name, value);
        if (value instanceof HttpSessionBindingListener)
            ((HttpSessionBindingListener) value).valueBound(event);
        // Notify interested application event listeners
        Context context = (Context) manager.getContainer();
        Object listeners[] = context.getApplicationListeners();
        if (listeners == null)
            return;
        for (int i = 0; i < listeners.length; i++) {
            if (!(listeners[i] instanceof HttpSessionAttributeListener))
                continue;
            HttpSessionAttributeListener listener =
                (HttpSessionAttributeListener) listeners[i];
            try {
                if (unbound != null) {
                    fireContainerEvent(context,
                                       "beforeSessionAttributeReplaced",
                                       listener);
                    //属性值变更
                    listener.attributeReplaced(event);
                    fireContainerEvent(context,
                                       "afterSessionAttributeReplaced",
                                       listener);
                } else {
                    fireContainerEvent(context,
                                       "beforeSessionAttributeAdded",
                                       listener);
                    //属性值添加
                    listener.attributeAdded(event);
                    fireContainerEvent(context,
                                       "afterSessionAttributeAdded",
                                       listener);
                }
            } catch (Throwable t) {
                try {
                    if (unbound != null) {
                        fireContainerEvent(context,
                                           "afterSessionAttributeReplaced",
                                           listener);
                    } else {
                        fireContainerEvent(context,
                                           "afterSessionAttributeAdded",
                                           listener);
                    }
                } catch (Exception e) {
                    ;
                }
                // FIXME - should we do anything besides log these?
                log(sm.getString("standardSession.attributeEvent"), t);
            }
        }
    }
     //从指定输入流中读序列化信息
    private void readObject(ObjectInputStream stream)
        throws ClassNotFoundException, IOException {
        // Deserialize the scalar instance variables (except Manager)
        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 (debug >= 2)
            log("readObject() loading session " + id);
        // Deserialize the attribute count and attribute values
        if (attributes == null)
            attributes = new HashMap();
        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 (debug >= 2)
                log("  loading attribute '" + name +
                    "' with value '" + value + "'");
            synchronized (attributes) {
                attributes.put(name, value);
            }
        }
        isValid = isValidSave;
    }
//写数据到输出流中
    private void writeObject(ObjectOutputStream stream) throws IOException {
        // Write the scalar instance variables (except Manager)
        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 (debug >= 2)
            log("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 = null;
            synchronized (attributes) {
                value = attributes.get(keys[i]);
            }
            if (value == null)
                continue;
            else if (value instanceof Serializable) {
                saveNames.add(keys[i]);
                saveValues.add(value);
            }
        }
        // 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 (debug >= 2)
                    log("  storing attribute '" + saveNames.get(i) +
                        "' with value '" + saveValues.get(i) + "'");
            } catch (NotSerializableException e) {
                log(sm.getString("standardSession.notSerializable",
                                 saveNames.get(i), id), e);
                stream.writeObject(NOT_SERIALIZED);
                if (debug >= 2)
                    log("  storing attribute '" + saveNames.get(i) +
                        "' with value NOT_SERIALIZED");
            }
        }
    }
    // -------------------------------------------------------- Private Methods
    /**
     * Fire container events if the Context implementation is the
     * <code>org.apache.catalina.core.StandardContext</code>.
     *
     * @param context Context for which to fire events
     * @param type Event type
     * @param data Event data
     *
     * @exception Exception occurred during event firing
     */
    private void fireContainerEvent(Context context,
                                    String type, Object data)
        throws Exception {
        if (!"org.apache.catalina.core.StandardContext".equals
            (context.getClass().getName())) {
            return; // Container events are not supported
        }
        // NOTE:  Race condition is harmless, so do not synchronize
        if (containerEventMethod == null) {
            containerEventMethod =
                context.getClass().getMethod("fireContainerEvent",
                                             containerEventTypes);
        }
        Object containerEventParams[] = new Object[2];
        containerEventParams[0] = type;
        containerEventParams[1] = data;
        containerEventMethod.invoke(context, containerEventParams);
    }
                                      
    /**
     * Notify all session event listeners that a particular event has
     * occurred for this Session.  The default implementation performs
     * this notification synchronously using the calling thread.
     *
     * @param type Event type
     * @param data Event data
     */
    public void fireSessionEvent(String type, Object data) {
        if (listeners.size() < 1)
            return;
        SessionEvent event = new SessionEvent(this, type, data);
        SessionListener list[] = new SessionListener[0];
        synchronized (listeners) {
            list = (SessionListener[]) listeners.toArray(list);
        }
        for (int i = 0; i < list.length; i++)
            ((SessionListener) list[i]).sessionEvent(event);
    }
    //属性中的key值
    private String[] keys() {
        String results[] = new String[0];
        synchronized (attributes) {
            return ((String[]) attributes.keySet().toArray(results));
        }
    }
//关联他的日志实例打印日志
    private void log(String message) {
        if ((manager != null) && (manager instanceof ManagerBase)) {
            ((ManagerBase) manager).log(message);
        } else {
            System.out.println("StandardSession: " + message);
        }
    }
   //打印错误日志信息
    private void log(String message, Throwable throwable) {
        if ((manager != null) && (manager instanceof ManagerBase)) {
            ((ManagerBase) manager).log(message, throwable);
        } else {
            System.out.println("StandardSession: " + message);
            throwable.printStackTrace(System.out);
        }
    }
}
//该类是HttpSessionContext的假实现,为了满足HttpSession.getSessionContext()调用返回值信息。
final class StandardSessionContext implements HttpSessionContext {
    private HashMap dummy = new HashMap();
//返回所有的sessionid信息 数据按照Enumeration类型返回
 
    public Enumeration getIds() {
        return (new Enumerator(dummy));
    }
    public HttpSession getSession(String id) {
        return (null);
    }
}

                                              未完待续

你可能感兴趣的:(servlet解析演进(7)-session(1))