Coder 爱翻译 How Tomcat Works 第九章 第一部分
Chapter 9: Session Management
Catalina通过一个叫做manager的组件来支持session管理。manager是由org.apache.catalina.Manager接口表示。一个manager总是和一个context相关联的。manager负责创建、更新、销毁(使一个session失效)session对象和返回一个有效的session对象给请求组件。
servlet可以通过调用javax.servlet.http.HttpServletRequest接口的getSession方法来获取一个session对象。在默认连接器中org.apache.catalina.connector.HttpRequestBase类实现了HttpServletRequest接口。
public HttpSession getSession() { return (getSession(true)); } public HttpSession getSession(boolean create) { ... 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); ... session = manager.createSession(); if (session != null) return (session.getSession()); else return (null); }
Listing 9.1: The 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 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); } public StandardSession(Manager manager);
// session attributes private HashMap attributes = new HashMap(); // the authentication type used to authenticate our cached Principal, private transient String authType = null; private long creationTime = 0L; private transient boolean expiring = false; private transient StandardSessionFacade facade = null; private String id = null; private long lastAccessedTime = creationTime; // The session event listeners for this Session. private transient ArrayList listeners = new ArrayList(); private Manager manager = null; private int maxInactiveInterval = -1; // Flag indicating whether this session is new or not. private boolean isNew = false; private boolean isValid = false; private long thisAccessedTime = creationTime;
public HttpSession getSession() { if (facade == null) facade = new StandardSessionFacade(this); return (facade); }Listing 9.2: The expire method 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(); } }
Listing 9.3: The 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 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; }