How Tomcat Works学习笔记<九>

 

Session管理

         通过manager组件,catalina支持对会话(session)进行管理,manager组件表示为org.apache.catalina.Manager接口。管理器通常是与context一起协同工作。创建、修改和销毁session是manager的主要责任,当然它也负责像所有的request提供一个有效的session。

         一个servlet可以通过调用javax.servlet.http.HttpServletRequest接口的getSession方法获取会话,方法的实现在org.apache.catalina.connector.HttpReqestBase类里面:

public HttpSession getSession() {

        return (getSession(true));

    }

    public HttpSession getSession(boolean create) {

        if( System.getSecurityManager() != null ) {

            PrivilegedGetSession dp = new PrivilegedGetSession(create);

            return (HttpSession)AccessController.doPrivileged(dp);

        }

        return doGetSession(create);

    }

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

}

         默认情况下,管理器把它管理的session保存在内存中,同时也支持对session进行持久化,保存到文件或数据库当中。

会话(Session)

         在servlet编程当中,会话(session)对象用javax.servlet.http.HttpSession接口表示,其的基本实现类是org.apache.catalina.session包中StandardSession,出于安全考虑并不直接把该类提供给servlet,而是为其提供了一个门面类StandardSessionFacade,相关类图:

        

Session接口

         Session是catalina内部门面,其实现类StandardSession同时也实现了javax.servlet.http.HttpSession接口,接口定义如下:

         package org.apache.catalina;

import java.security.Principal;

import java.util.Iterator;

import javax.servlet.http.HttpSession;

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对象通常包含在管理器中,所以这里需要一个setManager和getManager方法,以便把session分配给容器,每个session通常需要一个唯一标识。

StandardSession类

    StandardSession类是Session接口的标准实现类,同时也实现了HttpSession接口,因为需要存储,它也是可序列号的,它的构造函数中需要提供一个Manager实例:

         public StandardSession(Manager manager) {

        super();

        this.manager = manager;

        if (manager instanceof ManagerBase)

            this.debug = ((ManagerBase) manager).getDebug();

}

提供一个getSession方法会返回StandarSession的门面类:

         public HttpSession getSession() {

        if (facade == null)

            facade = new StandardSessionFacade(this);

        return (facade);

}

一旦在一个指定的时间内没有操作会话,那么session将会自动失效:

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

        }

}

StandardSessionFacade类

    为了防止servlet操作session接口中的一些方法,catalina中为StandardSession类提供了一个门面类,只允许servlet调用HttpSession中的方法。

管理器(Manager)

    管理器用来管理session对象,Tomcat中定义了管理器接口:org.apache.catalina.Manager,同时提供了一个实现了管理器的公共方法的ManagerBase类,ManagerBase有两个子类:StandardManager和PersistentManagerBase。

    在运行时,StandardManager把session保存在内存中,停止是会写入文件中,再次使用时又会从文件把这些session重新加载到内存当中,Manager的实现关系图如下:

   

    其中DistributeManager只在Tomcat4中有。

Manager接口

Manager表示管理器组件,接口定义如下:

         package org.apache.catalina;

import java.beans.PropertyChangeListener;

import java.io.IOException;

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;

}

首先,通过getContainer和setContainer方法可以把Manager分配个context容器,creatSession方法创建一个session对象,add方法把session添加到缓冲池中,remove方法把session从缓冲池中移除,getMaxInactiveInterval和setMaxInactiveInterval方法设置当用户没有操作会话以后管理器销毁session的最大间隔秒数。

其次,load和upload方法支持把session持久化到数据库磁盘等存储器中。

ManagerBase类

         ManagerBase是一个抽象类,提供了对Manager接口的一些公共方法的实现。generateSessionId返回一个唯一的session标识。

         所有的活动的session被缓存在Map中:

protected HashMap sessions = new HashMap();

    向缓存map中添加移除session对象:

                   public void add(Session session) {

             synchronized (sessions) {

                 sessions.put(session.getId(), session);

             }

        }

                   public void remove(Session session) {

             synchronized (sessions) {

                 sessions.remove(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);

        }

StandardManager类

    StandardManager是Manager的标准实现类,会把session保存在内存中。它实现了LifeCycle接口,所以它可以启动和停止:

    public void run() {

        // Loop until the termination semaphore is set

        while (!threadDone) {

            threadSleep();

            processExpires();

        }

}

PersistentManagerBase类

    PersistentManagerBase类是所有持久化Manager的父类。

Stores

         Manager通过org.apache.catalina.Store接口来管理session存储,接口定义如下:

         package org.apache.catalina;

import java.beans.PropertyChangeListener;

import java.io.IOException;

public interface Store {

        public String getInfo();

        public Manager getManager();

        public void setManager(Manager manager);

        public int getSize() throws IOException;

        public void addPropertyChangeListener(PropertyChangeListener listener);

        public String[] keys() throws IOException;

        public Session load(String id)throws ClassNotFoundException, IOException;

        public void remove(String id) throws IOException;

        public void clear() throws IOException;

        public void removePropertyChangeListener(PropertyChangeListener listener);

        public void save(Session session) throws IOException;

}

最重要的是save和load方法,用来保存和加载session,有一个StoreBase类提供公共方法的实现,StoreBase类有两个类FileStore和JDBCStore,分别把session保存在文件和数据库中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值