博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
servlet解析演进(7)-session(1)
阅读量:6697 次
发布时间:2019-06-25

本文共 27467 字,大约阅读时间需要 91 分钟。

hot3.png

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

1、session类

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

125940_FDa1_166980.png

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 java.lang.Method for the     * fireContainerEvent() method of the     * org.apache.catalina.core.StandardContext 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 fireContainerEvent 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     * org.apache.catalina.core.StandardContext.     *     * @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);    }}

                                              未完待续

转载于:https://my.oschina.net/zjItLife/blog/614027

你可能感兴趣的文章
DOM剪切板
查看>>
10.高效分布
查看>>
装饰器概念及运用
查看>>
CCF 201312-4 有趣的数
查看>>
screenX clientX pageX的区别
查看>>
android之自定义广播
查看>>
cAdvisor+InfluxDB+Grafana 监控Docker
查看>>
在 PowerPoint 2016 中嵌入网页
查看>>
C#关键字的使用
查看>>
操作系统常考知识点总结(1)
查看>>
Find Minimum in Rotated Sorted Array II
查看>>
spring 第一天:1015
查看>>
JavaScript 几种简单的table切换
查看>>
DevExpress控件使用经验总结
查看>>
软件包管理 之 fedora-rpmdevtools 工具介绍
查看>>
远程连接mysql数据库,1130问题
查看>>
解决win7的outlook打不开的问题
查看>>
Redis配置文件参数说明
查看>>
TSQL 根据表名生成UPDATE SELECT INSERT
查看>>
Java第五次作业--面向对象高级特性(抽象类和接口)
查看>>