tomcat源码解析--Session
tomcat 如何管理 session 相关的数据 及 session的使用1. 见tomcat中相关session接口的实现
session 接口: 主要包含一些session的常用 功能的方法定义, 包括:
setId/getId sessionID操作
getLastAccessedTime/access 最后访问时间操作
setMaxInactiveInterval/getMaxInactiveInterval 访问最大间隔
expire 过期操作
等等
HttpSession 接口 则是在 javax.servlet.http 包中的
包含了一些J2EE定义的session规则方法,如
getId
getLastAccessedTime
getServletContext 得到javax.servlet.ServletContext
getMaxInactiveInterval
getAttribute
等等
StandardSession是在tomcat org.apache.catalina.session 包中实现上面两个接口的实体类
关联了一个Manager (session管理器)之后讲
关联了一个sessionFacade 作为session的门面
然后定义了session 处理中的一些默认常量
getSession 方法
public HttpSession getSession() {
if (facade == null){
if (SecurityUtil.isPackageProtectionEnabled()){
final StandardSession fsession = this;
facade = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction(){
public Object run(){
return new StandardSessionFacade(fsession);
}
});
} else {
facade = new StandardSessionFacade(this);
}
}
return (facade);
}
主要就是返回当前StandardSession的facade
isValid 方法,验证是否有效
public boolean isValid() {
if (this.expiring) {
return true;
}
if (!this.isValid) {
return false;
}
if (ACTIVITY_CHECK && accessCount.get() > 0) {
return true;
}
if (maxInactiveInterval >= 0) {
long timeNow = System.currentTimeMillis();
int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
if (timeIdle >= maxInactiveInterval) {
expire(true);
}
}
return (this.isValid);
}
expire方法
先设置classloader, 然后 发起事件
expiring = true;
// Notify interested application event listeners
// FIXME - Assumes we call listeners in reverse order
Context context = (Context) manager.getContainer();
// The call to expire() may not have been triggered by the webapp.
// Make sure the webapp's class loader is set when calling the
// listeners
ClassLoader oldTccl = null;
if (context.getLoader() != null &&
context.getLoader().getClassLoader() != null) {
oldTccl = Thread.currentThread().getContextClassLoader();
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
context.getLoader().getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader(
context.getLoader().getClassLoader());
}
}
try {
Object listeners[] = context.getApplicationLifecycleListeners();
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 instanceof HttpSessionListener))
continue;
HttpSessionListener listener =
(HttpSessionListener) listeners;
try {
fireContainerEvent(context,
"beforeSessionDestroyed",
listener);
listener.sessionDestroyed(event);
fireContainerEvent(context,
"afterSessionDestroyed",
listener);
} catch (Throwable t) {
try {
fireContainerEvent(context,
"afterSessionDestroyed",
listener);
} catch (Exception e) {
// Ignore
}
manager.getContainer().getLogger().error
(sm.getString("standardSession.sessionEvent"), t);
}
}
}
然后交由session管理器,处理相关操作
session销毁
退出登录
移除相关session的key
long timeNow = System.currentTimeMillis();
int timeAlive = (int) ((timeNow - creationTime)/1000);
synchronized (manager) {
if (timeAlive > manager.getSessionMaxAliveTime()) {
manager.setSessionMaxAliveTime(timeAlive);
}
int numExpired = manager.getExpiredSessions();
if (numExpired < Integer.MAX_VALUE) {
numExpired++;
manager.setExpiredSessions(numExpired);
}
int average = manager.getSessionAverageAliveTime();
// Using long, as otherwise (average * numExpired) might overflow
average = (int) (((((long) average) * (numExpired - 1)) + timeAlive)
/ numExpired);
manager.setSessionAverageAliveTime(average);
}
if (manager instanceof ManagerBase) {
ManagerBase mb = (ManagerBase) manager;
SessionTiming timing = new SessionTiming(timeNow, timeAlive);
synchronized (mb.sessionExpirationTiming) {
mb.sessionExpirationTiming.add(timing);
mb.sessionExpirationTiming.poll();
}
}
// Remove this session from our manager's active sessions
manager.remove(this);
// Notify interested session event listeners
if (notify) {
fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
}
// Call the logout method
if (principal instanceof GenericPrincipal) {
GenericPrincipal gp = (GenericPrincipal) principal;
try {
gp.logout();
} catch (Exception e) {
manager.getContainer().getLogger().error(
sm.getString("standardSession.logoutfail"),
e);
}
}
// We have completed expire of this session
expiring = false;
// Unbind any objects associated with this session
String keys[] = keys();
for (int i = 0; i < keys.length; i++)
removeAttributeInternal(keys, notify);
readObject 读取 流, 初始化session (读取session文件初始化session)
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 (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("readObject() loading session " + id);
// Deserialize the attribute count and attribute values
if (attributes == null)
attributes = new Hashtable();
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 (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug("loading attribute '" + name +
"' with value '" + value + "'");
attributes.put(name, value);
}
isValid = isValidSave;
if (listeners == null) {
listeners = new ArrayList();
}
if (notes == null) {
notes = new Hashtable();
}
writeObject 写出到流
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 (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("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 = attributes.get(keys);
if (value == null)
continue;
else if ( (value instanceof Serializable)
&& (!exclude(keys) )) {
saveNames.add(keys);
saveValues.add(value);
} else {
removeAttributeInternal(keys, true);
}
}
// 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 (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("storing attribute '" + saveNames.get(i) +
"' with value '" + saveValues.get(i) + "'");
} catch (NotSerializableException e) {
manager.getContainer().getLogger().warn
(sm.getString("standardSession.notSerializable",
saveNames.get(i), id), e);
stream.writeObject(NOT_SERIALIZED);
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("storing attribute '" + saveNames.get(i) +
"' with value NOT_SERIALIZED");
}
}
页:
[1]