文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
分析整理的版本为 Ovirt 3.4.5 版本。
- engine 的 session 交由 SessionDataContainer 单例对象统一处理。
用户登录
通过 LoginBaseCommand 的 attachUserToSession 方法实现。
- 登录成功,将用户添加到 session 中。
SessionDataContainer.getInstance().setUser(getParameters().getSessionId(), getCurrentUser());
- 同时设置 登录 IP,登录方式 等。
SessionDataContainer.getInstance().setUserIp(getParameters().getIp());
SessionDataContainer.getInstance().setKind(getParameters().getKind());
用户登出
通过 LogoutUserCommand 的 executeCommand() 方法实现。
- 登出,将用户从 session 中删除。
public final void removeSession(String sessionId) {
oldContext.remove(sessionId);
newContext.remove(sessionId);
}
session 实现原理分析
- SessionDataContainer 对象中,提供了两个 session 列表。
- oldContext 中保存旧的 session。
- newContext 中保存新的 session。
- 将 SessionDataContainer 放入 engine 的后台调度,每 30 分钟,执行一次 cleanExpiredUsersSessions 方法。
SchedulerUtilQuartzImpl.getInstance().scheduleAFixedDelayJob(SessionDataContainer.getInstance(),
"cleanExpiredUsersSessions", new Class[] {}, new Object[] {},
sessionTimeoutInterval,
sessionTimeoutInterval, TimeUnit.MINUTES);
@TypeConverterAttribute(Integer.class)
@DefaultValueAttribute("30")
UserSessionTimeOutInterval,
@OnTimerMethodAnnotation("cleanExpiredUsersSessions")
public final void cleanExpiredUsersSessions() {
deleteOldGeneration();
}
- cleanExpiredUsersSessions 方法中,用 newContext 覆盖 oldContext,再重新创建 newContext。
private Map<String, Map<String, Object>> deleteOldGeneration() {
Map<String, Map<String, Object>> temp = oldContext;
oldContext = newContext;
newContext = new ConcurrentHashMap<String, Map<String, Object>>();
return temp;
}
-
session 的生命周期
- 将数据加入 newContext 列表。
- 数据由 newContext 列表迁移到 oldContext 列表。
- oldContext 数据被其他 newContext 数据所覆盖而过期。
-
session 的续签
public final Object getData(String sessionId, String key, boolean refresh) {
Map<String, Object> currentContext = null;
if ((currentContext = newContext.get(sessionId)) != null) {
return currentContext.get(key);
}
if (refresh) {
if ((currentContext = oldContext.remove(sessionId)) != null) {
newContext.put(sessionId, currentContext);
}
} else {
currentContext = oldContext.get(sessionId);
}
if (currentContext != null) {
return currentContext.get(key);
}
return null;
}
用户在界面上进行功能操作,使用 session,执行 getData 方法,设置 refresh 为 true,表明续签 session。
该操作会将 session 数据由 oldContext 列表迁移到 newContext 列表,并且等待下一次的 cleanExpiredUsersSessions 调用。
-
session 的数据过期
- 如果用户在规定时间内,未进行界面操作,数据从 newContext 列表迁移到 oldContext 列表,再被其他 newContext 数据覆盖而过期。
- session 从 newContext 列表迁移到 oldContext 列表的时间间隔为 30 分钟。oldContext 中的 session 失效也是 30 分钟。
- session 数据在 newContext 列表即将迁移的最后一分钟加入,则该 session 最长失效时间为 31 分钟。
- session 数据在 newContext 列表迁移后一分钟加入,则该 session 最长失效时间为 59 分钟。
-
session 的检测处理
- ApplicationPlaceManager 中绑定了界面区域变化操作,如果发现 session 不存在,则退出系统。
@Override
public void revealDefaultPlace() {
// revealPlace(getDefaultPlace());
PlaceRequest pr = getDefaultPlace();
if (pr == null) {
Window.Location.replace("/"); //$NON-NLS-1$
} else {
revealPlace(pr);
}
}
protected PlaceRequest getDefaultPlace() {
if (user.isLoggedIn()) {
return getDefaultMainSectionPlace();
} else {
// return defaultLoginSectionRequest;
return null;
}
}
-
session 的读取
- 首先从 newContext 列表中读取,未发现再从 oldContext 列表中读取。
网友评论