- 浏览: 238647 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
mhsjlove:
正则表达式的捕获组比这好用多了
高效率分离字符串到一个Map中 -
yk0025:
正在研究中。。。
Antx学习总结 -
asialee:
博主这块写的挺好的,我完全看了,不过我也写了一些关于编解码器的 ...
Netty源代码框架剖析( 二 ) -
he_wen:
不能够停止tomcat的话 kill -9 进程号 得到进程 ...
检查tomcat是否宕机 -
zhangyou1010:
catalina.sh stop 如果这个不能停止tomc ...
检查tomcat是否宕机
第九章、会话管理
一、前言部分
Catalina通过一个叫做manager的组件来支持会话管理,它是由org.apache.catalina.Manager接口代表。A manager一直与context相关联,还有就是manager负责创建、更新、销毁会话对象同时也会返回任何组件所需要的有效的会话对象。
一个servlet通过调用javax.servlet.http.HttpServletRequest接口中的getSession方法获得一个session对象,该接口是在默认连接器里由org.apache.catalina.connector.HttpRequestBase类实现的。这里在HttpRequestBase类中有一些相关的方法。
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); }
默认下,一个manager把所有的sessions对象存储在内存中。然而,Tomcat也允许一个manager把会话对象存放在文件只能够或者数据库(通过JDBC)。Catalina提供了org.apache.catalina.session包,里面包含了会话对象和会话管理类型。
这章从三个部分解释在Catalina中的会话管理:"Session", " Managers ", " Stores ".最后部分就用Context关联manager来解释这个应用程序。
二、会话
在servlet程序设计中,一个会话对象由javax.servlet.http.HttpSession接口代表,此接口实现的类是StandardSession(在org.apache.catalina.session包中)。然而,对于安全考虑,manager不会传给一个StandardSession实例给servlet,相反它把自己封装了一次,该类的名字是StandardSessionFacade(在org.apache.catalina.session包中)。注解:看到没有又用来了门面模式啦。。。。 。实际上,manager与另外一个门面(org.apache.catalina.Session接口)协调工作。下面的UML图是关于会话相关的类型。注意为了使图精简我就把org.apache.catalina的前缀(Session, StandardSession,StandardSessionFacade)去掉.
三、The Session 接口
The Session 接口充当了Catalina内部门面角色。the Session接口的标准实现是StandardSession类,同时它也实现了javax.servlet.http.HttpSession接口,The Session接口下面的代码:
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); }
一个会话对象一直包含在一个manager中,the setManager和getManager方法目的是一个会话实例与一个manager相关联. 一个会话实例同时也有一个唯一的标志符( 通过The Context相关联的manager),Session标识符也能够被the setId和getId方法访问。the manager决定一个会话对象的有效性来调用The getLastAccessedTime方法,The manager调用了setValid方法是设置或者是重新设置一个会话对象的有效性。只要每次会话实例被访问,那么其方法就会被调用最近更新时间。最后,The manager能够使得一个会话对象过期,通过调用the expire方法; the getSession方法返回一个门面封装了的HttpSession对象。
四、The StandardSession类
The StandardSession类是实现The Session接口的标准实现。除此之外他还实现了javax.servlet.http.HttpSession接口和java.lang.Serializable(这个是为了使得会话对象能够序列化)接口。
The standardSession的构造函数接收一个Manager实例,目的是使得一个会话对象一直拥有一个Manager.
public StandardSession(Manager manager);
下面有一些重要的私有变量来维护状态, 注意the transient关键字是让这些变量不能序列化。
注意:在Tomcat5中以上的变量时保护的,而在Tomcat 4 中是私有变量。每个变量都有get/set 方法。
The getSession方法通过传this实例创建一个StandardSessionFacade对象:
public HttpSession getSession(){
if(facade == null)
facade=new StandardSessionFacade(this);
return facade;
}
在Manager中如果一个会话对象没有访问的这个时间段超出了the maxInactiveInternal变量的值那么此会话就过期。能使一个会话对象过期,是通过调用了The Session接口的expire方法。下面就给出在Tomcat 4中,在StanardSession类实现了这个接口的方法:
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(); } }
该方法的处理过程包括:设置内部变量,从Manager中移除The Session实例,触发一些事件。
五、The StandardSessionFacade类
为了传一个session对象给Servlet,Catalina实例化The StandardSession类并封装这个实例,在把它传给Servlet. 然而,传给Servlet的是一个StandardSessionFacade实例( 该类仅仅实现了javax.servlet.http.HttpSession接口 ),那为什么要这么做呢?答案是:为了让servlet程序设计者编程时,无法让HttpSession对象向上转型为StandardSession,这是因为仅仅让程序设计者访问公共的方法,而一些私有的方法不暴露给程序设计者。
六、Manager
一个Manager管理会话对象,例如:它能创建会话对象,也能销毁会话对象。一个Manager由org.apache.catalina.Manager接口代表。在Catalina中,the org.apache.catalina.session包中,包含了ManagerBase类(它实现了公有的功能)。The ManagerBase有两个直接的子类:StandardManager和PersistentManagerBase.
当容器运行时,The StandardManager在内存中存储会话对象。然而,如果停止,那么StandardManager把当前内存中所有的会话对象存储在一个文件中,当又重新启动时,又会重新加载这些会话对象。
PersistentManagerBase是manager的一个基本组件(它在二级存储中存储了会话对象),该类也有两个子类: PersistentManager和DistributedManager(给类仅仅在Tomcat 4中能够使用)。下面是UML类图,关于The Manager接口和其实现的类:
七、The Manager 接口
The Manager接口代表了一个Manager组件,下面是其接口的方法:
package org.apache.catalina; import java.beans.PropertyChangeListener; import java.io.IOException; public interface Manager { public Container getContainer(); /** * Set the Container with which this Manager is associated. * * @param container The newly associated Container */ public void setContainer(Container container); /** * Return the DefaultContext with which this Manager is associated. */ public DefaultContext getDefaultContext(); /** * Set the DefaultContext with which this Manager is associated. * * @param defaultContext The newly associated DefaultContext */ public void setDefaultContext(DefaultContext defaultContext); /** * Return the distributable flag for the sessions supported by * this Manager. */ public boolean getDistributable(); /** * Set the distributable flag for the sessions supported by this * Manager. If this flag is set, all user data objects added to * sessions associated with this manager must implement Serializable. * * @param distributable The new distributable flag */ public void setDistributable(boolean distributable); /** * Return descriptive information about this Manager implementation and * the corresponding version number, in the format * <code><description>/<version></code>. */ public String getInfo(); /** * Return the default maximum inactive interval (in seconds) * for Sessions created by this Manager. */ public int getMaxInactiveInterval(); /** * Set the default maximum inactive interval (in seconds) * for Sessions created by this Manager. * * @param interval The new default value */ public void setMaxInactiveInterval(int interval); // --------------------------------------------------------- Public Methods /** * Add this Session to the set of active Sessions for this Manager. * * @param session Session to be added */ public void add(Session session); /** * Add a property change listener to this component. * * @param listener The listener to add */ public void addPropertyChangeListener(PropertyChangeListener listener); /** * Construct and return a new session object, based on the default * settings specified by this Manager's properties. The session * id will be assigned by this method, and available via the getId() * method of the returned session. If a new session cannot be created * for any reason, return <code>null</code>. * * @exception IllegalStateException if a new session cannot be * instantiated for any reason */ public Session createSession(); /** * Return the active Session, associated with this Manager, with the * specified session id (if any); otherwise return <code>null</code>. * * @param id The session id for the session to be returned * * @exception IllegalStateException if a new session cannot be * instantiated for any reason * @exception IOException if an input/output error occurs while * processing this request */ public Session findSession(String id) throws IOException; /** * Return the set of active Sessions associated with this Manager. * If this Manager has no active Sessions, a zero-length array is returned. */ public Session[] findSessions(); /** * Load any currently active sessions that were previously unloaded * to the appropriate persistence mechanism, if any. If persistence is not * supported, this method returns without doing anything. * * @exception ClassNotFoundException if a serialized class cannot be * found during the reload * @exception IOException if an input/output error occurs */ public void load() throws ClassNotFoundException, IOException; /** * Remove this Session from the active Sessions for this Manager. * * @param session Session to be removed */ public void remove(Session session); /** * Remove a property change listener from this component. * * @param listener The listener to remove */ public void removePropertyChangeListener(PropertyChangeListener listener); public void unload() throws IOException; }
首先,The Manager接口有getContainer和setContainer方法目的是一个实现Manager接口类与一个Context相关联。The CreateSession方法就是创建一个会话对象。The add方法把会话实例添加到会花池中,The remove方法是把会话对象从会话池中移除掉。The getMaxInactiveInternal和setMaxInactiveInternal方法返回(and specifices the number of sends the Manager will wait for the user associated with a session to come back before destorying the session).这里不会翻译。。。悲剧。。。
最后,the load和upload方法支持把可持续化的会话存储在第二个存储空间中(这个是有PersistManager中支持可持续化类型机制),The upload方法保存了当前激活的会话对象(也就是第一存储空间中该类时standardManger),并且the Load方法也支持把存储在第二存储空间的会话对象引入到内存中。
八、The ManagerBase类
The ManagerBase类是一个抽象类( 它的父类是Manager类 )。这个类为它的孩子提供公共的功能,此外,ManagerBase有一个createSession方法创建一个会话对象。每个session有一个唯一的标志符,这个标识符是由保护方法generateSessionId方法返回。
注意:一个激活的session是一个有效的会话对象,而没有过期。
一个特定的context下的Manager的实例管理整个激活的session. 这些激活的session存储在一个叫sessions的HashMap中:
protected HashMap sessions= new HashMap();
The add方法把一个session对象添加到sessions HashMap中,这个方法请看下面的代码:
public void add(Session session){
synchronized(sessions){
sessions.put(session.getId(),session);
}
}
The remove方法从HashMap中移除一个会话对象,下面是其方法代码:
public void remove(Session session){
synchronized(sessions){
sessions.remove(session.getId());
}
}
The findSession没有参数的方法,是返回全部激活的会话( 来自存放在HashMap中的全部激活的session,他转换成数组
)。The 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
The StandardManager类是Manager接口的一个标准实现,在内存中存储了整个会话对象,它也同时实现了The Lifecycle接口(请看在第六章、Lifecycle),这样就可以用start和stop来控制组件。实现stop方法中调用了upload方法(就是序列化有效的session实例到文件中,文件名字叫做SESSIONS.ser)。The SESSIONS.ser文件能够在CATALINA_HOME目录下找到。比如,在Tomcat 4和 Tomcat 5 中,如果 你运行本应用程序的代码,你就会发现在CATALINA_HOME/work/Standalone/localhost/examples目录下能找到SESSIONS.ser文件。当StandardManager有重新启动时,这些会话对象通过调用the Load方法全部读到内存中。
A Manager也负责销毁不再有效的会话对象。在Tomcat 4 中的StandardManager中,这样的实现,它是用了一个专门的线程来实现销毁会话对象。由于这个原因,StandardManager实现了 java.lang.Runnable, 请看下面实现run的方法:
public void run() { // Loop until the termination semaphore is set while (!threadDone) { threadSleep(); processExpires(); } }
The threadSleep方法调用了threadSleep(里面主要是Thread.sleep(checkInterval * 1000L)),the checkInterval变量是以秒为单位,默认值是60秒,也可以通过调用setCheckInterval方法改变这个值。
The processExpire方法: 循环遍历由StandardManager管理的整个会话对象,每个Session对象实例把lastAccessedTime变量与当前时间相比较。如果当前时间减去 lastAccessedTime的值大于 maxInactiveInternal,那么该方法就会调用The session接口中的expire方法使得会话该对象过期。The maxInactiveInternal的值通过调用setMaxInactiveInternal方法来改变这个值。在StandardManager中的maxInactiveInternal变量默认值是 60. 呵呵呵。。不要愚蠢的认为maxInactiveInternal值是在Tomcat部署的时候设置的。同时,The setContainer方法:它调用了the org.apache.catalina.core.ContainerBase类中的setManager方法(你一直都要调用setManager方法目的是context和Manager相关联),来重写这个值。下面是setContainer方法中的一些代码:
setMaxInactiveInternal((( Context ) this.container ).getSessionTimout() * 60 );
注意:the sessionTimeOut变量的默认值在org.apache.catalina.core.StandardContext类是30秒。在Tomcat 5中,The StandradManager类没有实现 java.lang.Runnable接口。在Tomcat 5 中的StandardManager对象中的The processExpires方法直接调用了the backgroundprocess方法,但是Tomcat 4不是这样做的。
public void backgroundProcess(){
processExpires();
}
在 StandardManager中的backgroundProcess方法是通过the org.apache.catalina.core.StandardContext实例(the Container和manager相关联)被调用的。StandardContext周期的调用了backgroundProcess方法这个将会在第十二章进行讨论。
十、PersistentManagerBase
The PersistentManagerBase类是整个可持久化管理的父类。StandardManager和 persistent manager主要的区别就是后者存在一个store,一个 store代表可管理session对象的第二级存储,The PersistentManagerBase类使用了一个私有引用对象(叫做store).
private Store store=null;
在一个可持久化管理中,整个session对象既能备份有能迁移。当一个会话对象备份时,The session 对象就会拷贝到一个store中,原始的那个还是会继续停留在内存中。因此,如果服务器崩溃了,激活的会话对象能够在the store中恢复过来。当一个session对象被迁移时,它就会被迁移到the store中,那为什么要这么做呢?这是因为,激活的会话对象的数目已经超出了一个特定的值或者The session对象已经停留在内存中太久并且从来没有用到过它。迁移的目的就是保存内存中的会话对象。注意激活的对象就是停留在内存中的对象。
在Tomcat 4 中PersistentManagerBase类实现了java.lang.Runnable接口,目的是使用一个独立的线程周期的备份和迁移激活的会话对象,下面是实现run方法的代码:
评论
最好用 DOCBOOK 组织一下,以便将来发布集中的文档。
我有一个DOCBOOK工具相关的项目,
http://hantsy-labs.googlecode.com
以前我翻译了 Spring Live全书,http://blog.chinaunix.net/u/1096/showart_88617.html
我的博客 http://hantsy.cublog.cn。
贵在坚持。
<div class="quote_div">
<p> </p>
<p style="text-align: center;"><strong><span style="font-size: large;">第九章、会话管理</span> </strong></p>
<p>一、前言部分</p>
<p> </p>
<p>Catalina通过一个叫做manager的组件来支持会话管理,它是由org.apache.catalina.Manager接口代表。A manager一直与context相关联,还有就是manager负责创建、更新、销毁会话对象同时也会返回任何组件所需要的有效的会话对象。</p>
<p> </p>
<p>一个servlet通过调用javax.servlet.http.HttpServletRequest接口中的getSession方法获得一个session对象,该接口是在默认连接器里由org.apache.catalina.connector.HttpRequestBase类实现的。这里在HttpRequestBase类中有一些相关的方法。</p>
<p> </p>
<p> </p>
<p> </p>
<pre name="code" class="java"> 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);
}
</pre>
<p> </p>
<p>默认下,一个manager把所有的sessions对象存储在内存中。然而,Tomcat也允许一个manager把会话对象存放在文件只能够或者数据库(通过JDBC)。Catalina提供了org.apache.catalina.session包,里面包含了会话对象和会话管理类型。</p>
<p> </p>
<p>这章从三个部分解释在Catalina中的会话管理:"Session", " Managers ", " Stores ".最后部分就用Context关联manager来解释这个应用程序。</p>
<p> </p>
<p>二、会话</p>
<p> </p>
<p>在servlet程序设计中,一个会话对象由javax.servlet.http.HttpSession接口代表,此接口实现的类是StandardSession(在org.apache.catalina.session包中)。然而,对于安全考虑,manager不会传给一个StandardSession实例给servlet,相反它把自己封装了一次,该类的名字是StandardSessionFacade(在org.apache.catalina.session包中)。<span style="background-color: #ff0000;">注解:看到没有又用来了门面模式啦。。。。</span> 。实际上,manager与另外一个门面(org.apache.catalina.Session接口)协调工作。下面的UML图是关于会话相关的类型。注意为了使图精简我就把org.apache.catalina的前缀(Session, StandardSession,StandardSessionFacade)去掉.</p>
<p> </p>
<p><br><img src="http://dl.iteye.com/upload/attachment/362896/8c0b2878-108f-37ed-8ab8-2634afad2f5f.png" alt=""></p>
<p>三、The Session 接口</p>
<p> </p>
<p>The Session 接口充当了Catalina内部门面角色。the Session接口的标准实现是StandardSession类,同时它也实现了javax.servlet.http.HttpSession接口,The Session接口下面的代码:</p>
<pre name="code" class="java">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);
}
</pre>
<p>一个会话对象一直包含在一个manager中,the setManager和getManager方法目的是一个会话实例与一个manager相关联. 一个会话实例同时也有一个唯一的标志符( 通过The Context相关联的manager),Session标识符也能够被the setId和getId方法访问。the manager决定一个会话对象的有效性来调用The getLastAccessedTime方法,The manager调用了setValid方法是设置或者是重新设置一个会话对象的有效性。只要每次会话实例被访问,那么其方法就会被调用最近更新时间。最后,The manager能够使得一个会话对象过期,通过调用the expire方法; the getSession方法返回一个门面封装了的HttpSession对象。</p>
<p> </p>
<p>四、The StandardSession类</p>
<p> </p>
<p>The StandardSession类是实现The Session接口的标准实现。除此之外他还实现了javax.servlet.http.HttpSession接口和java.lang.Serializable(这个是为了使得会话对象能够序列化)接口。</p>
<p> </p>
<p>The standardSession的构造函数接收一个Manager实例,目的是使得一个会话对象一直拥有一个Manager.</p>
<p> </p>
<p> public StandardSession(Manager manager);</p>
<p> </p>
<p>下面有一些重要的私有变量来维护状态, 注意the transient关键字是让这些变量不能序列化。</p>
<p> </p>
<p><br><img src="http://dl.iteye.com/upload/attachment/369099/64876f35-4d58-3634-b2e3-7e4f0f78212e.png" alt=""><br> 注意:在Tomcat5中以上的变量时保护的,而在Tomcat 4 中是私有变量。每个变量都有get/set 方法。</p>
<p> </p>
<p>The getSession方法通过传this实例创建一个StandardSessionFacade对象:</p>
<p> </p>
<p> public HttpSession getSession(){</p>
<p> if(facade == null)</p>
<p> facade=new StandardSessionFacade(this);</p>
<p> return facade;</p>
<p> }</p>
<p> </p>
<p>在Manager中如果一个会话对象没有访问的这个时间段超出了the maxInactiveInternal变量的值那么此会话就过期。能使一个会话对象过期,是通过调用了The Session接口的expire方法。下面就给出在Tomcat 4中,在StanardSession类实现了这个接口的方法:</p>
<p> </p>
<pre name="code" class="java">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();
}
}</pre>
<p> </p>
<p> </p>
<p> </p>
<p>该方法的处理过程包括:设置内部变量,从Manager中移除The Session实例,触发一些事件。</p>
<p> </p>
<p>五、The StandardSessionFacade类</p>
<p> </p>
<p>为了传一个session对象给Servlet,Catalina实例化The StandardSession类并封装这个实例,在把它传给Servlet. 然而,传给Servlet的是一个StandardSessionFacade实例( 该类仅仅实现了javax.servlet.http.HttpSession接口 ),那为什么要这么做呢?答案是:为了让servlet程序设计者编程时,无法让HttpSession对象向上转型为StandardSession,这是因为仅仅让程序设计者访问公共的方法,而一些私有的方法不暴露给程序设计者。</p>
<p> </p>
<p>六、Manager</p>
<p> </p>
<p>一个Manager管理会话对象,例如:它能创建会话对象,也能销毁会话对象。一个Manager由org.apache.catalina.Manager接口代表。在Catalina中,the org.apache.catalina.session包中,包含了ManagerBase类(它实现了公有的功能)。The ManagerBase有两个直接的子类:StandardManager和PersistentManagerBase.</p>
<p> </p>
<p>当容器运行时,The StandardManager在内存中存储会话对象。然而,如果停止,那么StandardManager把当前内存中所有的会话对象存储在一个文件中,当又重新启动时,又会重新加载这些会话对象。</p>
<p> </p>
<p>PersistentManagerBase是manager的一个基本组件(它在二级存储中存储了会话对象),该类也有两个子类: PersistentManager和DistributedManager(给类仅仅在Tomcat 4中能够使用)。下面是UML类图,关于The Manager接口和其实现的类:</p>
<p> </p>
<p><br><img src="http://dl.iteye.com/upload/attachment/369111/8067d00f-edbf-33ae-9b84-2c2c5d5b453e.png" alt=""></p>
<p>七、The Manager 接口</p>
<p> </p>
<p>The Manager接口代表了一个Manager组件,下面是其接口的方法:</p>
<p> </p>
<pre name="code" class="java">package org.apache.catalina;
import java.beans.PropertyChangeListener;
import java.io.IOException;
public interface Manager {
public Container getContainer();
/**
* Set the Container with which this Manager is associated.
*
* @param container The newly associated Container
*/
public void setContainer(Container container);
/**
* Return the DefaultContext with which this Manager is associated.
*/
public DefaultContext getDefaultContext();
/**
* Set the DefaultContext with which this Manager is associated.
*
* @param defaultContext The newly associated DefaultContext
*/
public void setDefaultContext(DefaultContext defaultContext);
/**
* Return the distributable flag for the sessions supported by
* this Manager.
*/
public boolean getDistributable();
/**
* Set the distributable flag for the sessions supported by this
* Manager. If this flag is set, all user data objects added to
* sessions associated with this manager must implement Serializable.
*
* @param distributable The new distributable flag
*/
public void setDistributable(boolean distributable);
/**
* Return descriptive information about this Manager implementation and
* the corresponding version number, in the format
* <code>&lt;description&gt;/&lt;version&gt;</code>.
*/
public String getInfo();
/**
* Return the default maximum inactive interval (in seconds)
* for Sessions created by this Manager.
*/
public int getMaxInactiveInterval();
/**
* Set the default maximum inactive interval (in seconds)
* for Sessions created by this Manager.
*
* @param interval The new default value
*/
public void setMaxInactiveInterval(int interval);
// --------------------------------------------------------- Public Methods
/**
* Add this Session to the set of active Sessions for this Manager.
*
* @param session Session to be added
*/
public void add(Session session);
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Construct and return a new session object, based on the default
* settings specified by this Manager's properties. The session
* id will be assigned by this method, and available via the getId()
* method of the returned session. If a new session cannot be created
* for any reason, return <code>null</code>.
*
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*/
public Session createSession();
/**
* Return the active Session, associated with this Manager, with the
* specified session id (if any); otherwise return <code>null</code>.
*
* @param id The session id for the session to be returned
*
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
* @exception IOException if an input/output error occurs while
* processing this request
*/
public Session findSession(String id) throws IOException;
/**
* Return the set of active Sessions associated with this Manager.
* If this Manager has no active Sessions, a zero-length array is returned.
*/
public Session[] findSessions();
/**
* Load any currently active sessions that were previously unloaded
* to the appropriate persistence mechanism, if any. If persistence is not
* supported, this method returns without doing anything.
*
* @exception ClassNotFoundException if a serialized class cannot be
* found during the reload
* @exception IOException if an input/output error occurs
*/
public void load() throws ClassNotFoundException, IOException;
/**
* Remove this Session from the active Sessions for this Manager.
*
* @param session Session to be removed
*/
public void remove(Session session);
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
public void unload() throws IOException;
}
</pre>
<p>首先,The Manager接口有getContainer和setContainer方法目的是一个实现Manager接口类与一个Context相关联。The CreateSession方法就是创建一个会话对象。The add方法把会话实例添加到会花池<span style="background-color: #ff0000;">中,The remove方法是把会话对象从会话池中移除掉。The getMaxInactiveInternal和setMaxInactiveInternal方法返回(and specifices the number of sends the Manager will wait for the user associated with a session to come back before destorying the session).这里不会翻译。。。悲剧。。。</span> </p>
<p> </p>
<p>最后,the load和upload方法支持把可持续化的会话存储在第二个存储空间中(这个是有PersistManager中支持可持续化类型机制),The upload方法保存了当前激活的会话对象(也就是第一存储空间中该类时standardManger),并且the Load方法也支持把存储在第二存储空间的会话对象引入到内存中。</p>
<p> </p>
<p>八、The ManagerBase类</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
<p> </p>
发表评论
-
tomcat的请求流程
2011-12-27 09:59 3680该文章是摘自张华的博 ... -
《How Tomcat Works》翻译(9) 之 会话管理续集
2010-12-19 22:02 1415八、The ManagerBase类 The Mana ... -
《How Tomcat Works》翻译(7) 之 Tomcat类加载器续集
2010-12-07 17:18 1795一、The Loader接口 在 ... -
《How Tomcat Works》翻译(6) 之 类加载器
2010-12-07 15:22 1680第八章 、Loader加载器 一、前言部分 ... -
《How Tomcat Works》翻译(5)之 日志续集
2010-12-07 10:22 1272七、The FileLogger类 The F ... -
《How Tomcat Works》翻译(5)之 日志
2010-12-06 21:09 1393第七章、日志 一、前言部分 A Logger ... -
《How Tomcat Works》翻译(4)之 生命周期
2010-12-05 22:19 1347第六章 生命周期 一 ... -
《How Tomcat Works》翻译(3)之Context容器
2010-12-05 19:09 1990一、The Context应用 在这章的第一个应用程 ... -
How Tomcat works 翻译(2) 之 Wrapper容器
2010-12-03 22:42 2290第五章、容器 ... -
How Tomcat works 翻译(1) 之 说明部分
2010-12-03 20:12 2116首先,由于本人读《How Tomcat works》 ...
相关推荐
通过阅读《How Tomcat Works》中文版,读者将能够获得对Tomcat架构的全面理解,学习到如何从源码级别研究和开发一个高性能的Java应用服务器,以及如何将其应用于实际的Web开发和服务器管理工作中。
9. **源码分析**:深入源码有助于理解Tomcat的工作流程,例如Servlet容器如何解析请求、如何调用Servlet的生命周期方法,以及如何处理会话管理等。 10. **扩展性**:Tomcat可以通过添加Valve组件来扩展其功能,...
### How Tomcat Works中文版深度解析 #### 一、引言与概述 《How Tomcat Works》是一本针对Apache Tomcat服务器内部工作机制进行深入剖析的专业书籍。本书详细介绍了Tomcat 4.1.12和5.0.18两个版本的内部结构与...
《How Tomcat Works中文版》这本书是一本深入探讨Apache Tomcat服务器工作原理的专著。Apache Tomcat服务器,或简称为Tomcat,是世界上广泛使用的Java Servlet容器和JavaServer Pages(JSP)引擎,负责处理基于Java...
首先,从标题和描述我们可以得知,这个压缩包包含两部分内容:《HowTomcatWorks》的中文翻译和源码。这使得我们能够从理论和实践两个层面去了解Tomcat。中文版的书籍可以帮助中国开发者消除语言障碍,更深入地理解...
《How Tomcat Works》是一本深入解析Apache Tomcat工作原理的书籍,同时也包含了源码,为读者提供了理论与实践相结合的深入学习体验。Tomcat是一款广泛使用的开源Java Servlet容器,它是Apache软件基金会 Jakarta...
通过阅读《How Tomcat Works》中文版和分析源码,开发者不仅可以了解到Tomcat的基本架构,还能深入到细节,理解其在处理请求、管理会话、加载资源等方面的具体实现。这对于优化Web应用性能、调试问题、扩展Tomcat...
"HowTomcatWorks"项目,正如其名,旨在帮助开发者了解Tomcat的工作原理,通过源代码分享,使我们有机会深入探究这个强大的服务器内部机制。 1. **Tomcat架构概览** Tomcat的架构设计分为几个主要部分:Catalina...
《How Tomcat Works》这本书深入剖析了Tomcat服务器的工作原理,是Java开发者深入理解Servlet容器不可或缺的参考资料。Tomcat作为Apache软件基金会的项目,是开源的、轻量级的Servlet和JSP容器,广泛应用于各种Web...
《How Tomcat Works》这本书详细解释了Tomcat的工作原理,它不仅为新手提供了一个蓝图,帮助他们理解这个复杂的系统,也为有经验的开发者提供了深入学习的机会。 ### Tomcat的基本概念 Tomcat核心分为两个主要模块...
通过阅读源码,开发者可以了解Tomcat内部的详细实现,包括线程池管理、会话管理、安全控制等,这对于解决复杂问题和定制化开发非常有帮助。 在实际操作中,还会涉及到Tomcat的部署和配置,如修改server.xml配置文件...
Tomcat提供JNDI服务,允许Web应用查找和绑定资源,如数据源、邮件会话等,方便应用的配置和管理。 10. **性能优化** Tomcat的性能可以通过调整各种配置参数进行优化,如最大线程数、最小空闲线程数、连接超时、...
"how-tomcat-works-master_howtomcatworks_"是一个关于Tomcat工作原理的源码分析项目,经过整理后可以在IntelliJ IDEA中直接运行,为开发者提供了一手的实践平台。 首先,我们要了解Tomcat的核心组件。Tomcat主要由...
《译How Tomcat Works(第二章)》这篇文章主要讲解了Apache Tomcat服务器的工作原理,它是一个开源的Java Servlet容器,广泛用于部署Web应用程序。在这一章中,我们将深入探讨Tomcat如何处理HTTP请求,以及其内部架构...