《How tomcat works》读书笔记_Session Management

Session

在servlet中Session对象是由javax.servlet.http.HttpSession接口来表示的。这个接口的实现类为org.apache.catalina.session包中的StandardSession类。然而出于安全考虑管理器并不会将StandardSession实例直接传递给servlet,它会传递一个门面类StandardSessionFacade。

Session Interface

package org.apache.catalina; import java.io.IOException; 
import java.security.Principal; 
import java.util.Iterator; 
import javax.servlet.ServletException; 
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 long getCreationTime(); 
    public void setCreationTime(long time); 
    public void setId(String id); 
    public String getInfo(); 
    public long getLastAccessedTime();
    public Manager getManager(); 
    public int getMaxInactiveInterval(); 
    public void setMaxInactiveInterval(int interval); 
    public Principal getPrincipal();
    public void setPrincipal(Principal principal); 
    public HttpSession getSession(); 
    public boolean isValid();
    public void access(); 
    public void expire(); 
    public Iterator getNoteNames(); 
    public void removeNote(String name); 
    public void setNote(String name, Object value); }

The StandardSession Class

StandardSession类是Session接口的标准实现,另外在实现了javax.servlet.http.HttpSession和org.apache.catalina.Session接口的同时StandardSession还实现了java.lang.Serializable接口,以方便对Session对象时行序列化。

这个类的构造函数强制要求传一个Manager对象,强制每个Session都于一个Manager关联。

public StandardSession(Manager manager);

getSession方法会通过当前对象创建它的一个门面类StandardSessionFacade。

public HttpSession getSession() { 
    if (facade == null) 
        facade = new StandardSessionFacade(this); 
    return (facade); 
}

Manager

管理 Session对象,它负责生成Session对象并在需要的时候销毁这些对象。一个Manager由org.apache.catalina.Manager接口来表示。在Catalina中,org.apache.catalina.session包的ManagerBase类提供基本功能的实现,ManagerBase有两个子类:StandardManager和PersistentManagerBase。

运行时,StandardManager将Session对象保存在内存中。当其停止时,它会将当前所有的Session对象保存一个文件中,再次启动时再重新加载这些对象。

PersistentManagerBase是Manager组件的一个基础类,它将Session对象保存在一个二级储存中。它有两个子类:PersistentManager和DistributedManager(DistributedManager只在Tomcat4中使用)

Manager Interface

package org.apache.catalina; 
import java.beans.PropertyChangeListener; 
import java.io.IOException; 

public interface Manager { 
    public Container getContainer(); 
    public void setContainer(Container container); 
    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 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; 
}

首先,Manager接口中的setContainer和getContainer方法用来将Manager的实现类同Context关联。createSession方法用来创建一个Session对象。add方法用于在Session池中添加一个Session对象remove方法用于在Session池中删除一个Session对象。getMaxInactiveInterval方法和setMaxInactiveInterval方法用于获取或是设置Session对象最大的生存周期。

最后,load和unload方法用于将Session对象保存在一个二级储存中。

ManagerBase Class

ManagerBase是一个抽象类,所有的Manager实现类都需要继承这个类。ManagerBase为它子类实现了部分基本功能。另外,ManagerBase类中的createSession方法创建Session对象。每一个Session都有一个唯一的标识符。ManagerBase类中的protected方法generateSessionId可以返回一个唯一标识符。

对于一个Context中的Manager实例,它负责所有在Context中活跃的Session对象,这些活跃的Session对象被保存在一个名为sessions的HashMap中

protected HashMap sessions = new HashMap();

add方法会添加一个Session对象到HashMap中

public void add(Session session) {
    synchronized (sessions) {
        sessions.put(session.getId(), session);
    }
}

remove方法会从HashMap中删除一个指定的Session

public void remove(Session session) {
    synchronized (sessions) {
        sessions.remove(session.getId());
    }
}

无参的findSession方法会以数组形式返回所有在HashMap中活跃的Session对象,以SessionId为参的findSession方法会返回指定的Session对象。

    public Session[] findSessions() {

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

    }

    public Session findSession(String id) throws IOException {

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

    }

StandardManager

StandardManager类是Manager接口的标准实现,它将Session对象保存在内存中。它实现了LifeCycel接口,所以它可以被启动或是停用。在它的stop方法实现中,会调用unload方法序列化所有有效的Session对象到一个名为SESSIONS.ser的文件中。这个文件可以在CATALINA_HOME下找到。当这个Manager重新启动时就会调用load方法重新加载这些Session对象。

Manager同进负责销毁无效的Session对象,在Tomcat4中会有一个专门的线程来负责。所以StandardManager实现了java.lang.Runnable接口。下面是在Tomcat4中StandardManager类的run方法

    public void run() {

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

    }

threadSleep方法使线程休眠由checkInterval变量指定的时间,默认值为60,可以调用setCheckInterval方法来重新设置这个值。

processExpire方法循环遍历所有Manager管理的Session对象,对比这些Session对象的失效时间与当前时间,对于失效的Session对象直接调用Session接口的expire方法。maxInactiveInternal变量可以通过setMaxInactiveInterval方法来修改。

在Tomcat5中,StandardManager没有实现java.lang.Runnable接口。它的processExpires方法直接由backgroundprocess方法调用

public void backgroundProcess() { 
    processExpires(); 
}

backgroundProcess方法由org.apache.catalina.core.StandardContext类的backgroundProcess方法调用,这个将在后面的章节中讨论。

PersistentManagerBase

PersistentManagerBase是所有持久化Manager的父类,和StandardManager类的唯一区别就是它会持久化储存Session对象。PersistentManagerBase类使用了一个store的私有变量来保存所有Session对象,store代表一个二级储存。

private Store store = null;

在一个持久化的Manager中,Session对象可以被备份或是换出。当一个Session对象被备份时,Session对象会被复制到Store中同时它还会继续保留在内存中。因此,如果服务器宕机的话,还可以从Store中将这些Session对象恢复出来。当Session对象数量超过了一个指定的数值或是一个Session对象空闲太久的时候,它就会被换出。换出的主要目的就是为了节约内存。

在Tomcat4中,PersistentManagerBase实现了java.lang.Runnable接口,使用一个单独的线程定时去备份或是换出活跃的Session对象。

Swap Out

PersistentManagerBase会执行一系列来规则来确定是否换出Session对象。一般一个Session对象被换出是因为当前Session对象数量超过的当前所能容纳的最大值,或是一个Session对象长时间末被使用。

当拥有大量的Session对象时,PersistentManagerBase实例会随机换出Session对象直至Session数量等于可容纳Session对象的最大值。

当一个Session对象闲置太长时间时,PersistentManagerBase使用了两个变量minIdleSwap和maxIdleSwap来决定这个Session是否被换出。如果这个Session的lastAccessedTime变量值同时超过了minIdleSwap和maxIdleSwap变量的值,那么这个Session将会被换出。为了防止任何Session被换出,你可以为maxIdleSwap变量设置 一个负数的值。

由于一个活跃的Session可以被换出,它即可以在内存中也可以在Store中。因此,findSession (String id)方法会首先在内存中查找Session,如果内存中没有,再去Store中查找。

public Session findSession(String id) throws IOException { 
    Session session = super.findSession(id); 
    if (session != null) return (session); 
    // not found in memory, see if the Session is in the Store 
    // swapIn returns an active session in the Store
    session = swapIn(id); 
    return (session); 
}

Back-up

并不是所有活跃的Session都需要备份。PersistentManagerBase只会备份那些闲置时间超过maxIdleBackup变量值的Session对象。processMaxIdleBackups方法会执行Session的备份工作。

PersistentManager

PersistentManager继承自PersistentManagerBase。

package org.apache.catalina.session; 
public final class PersistentManager extends PersistentManagerBase { 
    // The descriptive information about this implementation. 
    private static final String info = "PersistentManager/1.0"; 
    // The descriptive name of this Manager implementation (for logging). 
    protected static String name = "PersistentManager"; 
    public String getInfo() {
        return (this.info); 
    } 
    public String getName() { 
        return (name); 
    } 
}

DistributedManager

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值