我在网上找了一个比较贴切的描述:

Session.Clear()就是把Session对象中的所有项目都删除了,Session对象里面啥都没有。但是Session对象还保留。Session.Abandon()就是把当前Session对象删除了,下一次就是新的Session了。(下一次新会话开始貌似并不会产生新的SESSIONID)主要的不同之处在于当使用Session.Abandon时,会调用Session_End方法(InProc模式下)。当下一个请求到来时将激发Session_Start方法。而Session.Clear只是清除Session中的所有数据并不会中止该Session,因此也不会调用那些方法。其中标红也不是很正确。

首先我们来看一下code:

Dictionary<string, HttpSessionState> dict = new Dictionary<string, HttpSessionState>();
// Abandon
dict.Remove(key);
//Clear()
dict[key].Clear();

假设session存储一个字典结构,key就是我们客户端的sessionID,value 就是我们的SessionSate(它也是一个集合),调用Abandon后就把key删除了,但是clear是value里面的内容清空了。这2个方法的实现大家可以参考HttpSessionStateContainer的实现,Clear 清空集合,Abandon设置变量使其属性IsAbandoned为true。

真正的核心code在SessionStateModule类的OnReleaseState方法里面,在有Session的Http请求中,有一个地方加载我们的session,也有一个地方保存我们的session。

  /// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
void OnReleaseState(Object source, EventArgs eventArgs) {
HttpApplication app;
HttpContext context;
bool setItemCalled = false; Debug.Trace("SessionStateOnReleaseState", "Beginning SessionStateModule::OnReleaseState"); Debug.Assert(!(_rqAddedCookie && !_rqIsNewSession),
"If session id was added to the cookie, it must be a new session."); // !!!
// Please note that due to InProc session id optimization, this function should not
// use _rqId directly because it can still be null. Instead, use DelayedGetSessionId(). _releaseCalled = true; app = (HttpApplication)source;
context = app.Context; ChangeImpersonation(context, false); try {
if (_rqSessionState != null) {
bool delayedSessionState = (_rqSessionState == s_delayedSessionState); Debug.Trace("SessionStateOnReleaseState", "Remove session state from context");
SessionStateUtility.RemoveHttpSessionStateFromContext(_rqContext, delayedSessionState); /*
* Don't store untouched new sessions.
*/ if (
// The store doesn't have the session state.
// ( Please note we aren't checking _rqIsNewSession because _rqIsNewSession
// is lalso true if the item is converted from temp to perm in a GetItemXXX() call.)
_rqSessionStateNotFound // OnStart is not defined
&& _sessionStartEventHandler == null // Nothing has been stored in session state
&& (delayedSessionState || !_rqSessionItems.Dirty)
&& (delayedSessionState || _rqStaticObjects == null || _rqStaticObjects.NeverAccessed)
) { Debug.Trace("SessionStateOnReleaseState", "Not storing unused new session.");
}
else if (_rqSessionState.IsAbandoned) {
Debug.Trace("SessionStateOnReleaseState", "Removing session due to abandonment, SessionId=" + _rqId); if (_rqSessionStateNotFound) {
// The store provider doesn't have it, and so we don't need to remove it from the store. // However, if the store provider supports session expiry, and we have a Session_End in global.asax,
// we need to explicitly call Session_End.
if (_supportSessionExpiry) {
if (delayedSessionState) {
Debug.Assert(s_allowDelayedStateStoreItemCreation, "s_allowDelayedStateStoreItemCreation");
Debug.Assert(_rqItem == null, "_rqItem == null"); InitStateStoreItem(false /*addToContext*/);
} _onEndTarget.RaiseSessionOnEnd(ReleaseStateGetSessionID(), _rqItem);
}
}
else {
Debug.Assert(_rqItem != null, "_rqItem cannot null if it's not a new session"); // Remove it from the store because the session is abandoned.
_store.RemoveItem(_rqContext, ReleaseStateGetSessionID(), _rqLockId, _rqItem);
}
}
else if (!_rqReadonly ||
(_rqReadonly &&
_rqIsNewSession &&
_sessionStartEventHandler != null &&
!SessionIDManagerUseCookieless)) {
// We need to save it since it isn't read-only
// See Dev10 588711: Issuing a redirect from inside of Session_Start event
// triggers an infinite loop when using pages with read-only session state // We save it only if there is no error, and if something has changed (unless it's a new session)
if ( context.Error == null // no error
&& ( _rqSessionStateNotFound
|| _rqSessionItems.Dirty // SessionItems has changed.
|| (_rqStaticObjects != null && !_rqStaticObjects.NeverAccessed) // Static objects have been accessed
|| _rqItem.Timeout != _rqSessionState.Timeout // Timeout value has changed
)
) { if (delayedSessionState) {
Debug.Assert(_rqIsNewSession, "Saving a session and delayedSessionState is true: _rqIsNewSession must be true");
Debug.Assert(s_allowDelayedStateStoreItemCreation, "Saving a session and delayedSessionState is true: s_allowDelayedStateStoreItemCreation");
Debug.Assert(_rqItem == null, "Saving a session and delayedSessionState is true: _rqItem == null"); InitStateStoreItem(false /*addToContext*/);
} #if DBG
if (_rqSessionItems.Dirty) {
Debug.Trace("SessionStateOnReleaseState", "Setting new session due to dirty SessionItems, SessionId=" + _rqId);
}
else if (_rqStaticObjects != null && !_rqStaticObjects.NeverAccessed) {
Debug.Trace("SessionStateOnReleaseState", "Setting new session due to accessed Static Objects, SessionId=" + _rqId);
}
else if (_rqSessionStateNotFound) {
Debug.Trace("SessionStateOnReleaseState", "Setting new session because it's not found, SessionId=" + _rqId);
}
else {
Debug.Trace("SessionStateOnReleaseState", "Setting new session due to options change, SessionId=" + _rqId +
"\n\t_rq.timeout=" + _rqItem.Timeout.ToString(CultureInfo.InvariantCulture) +
", _rqSessionState.timeout=" + _rqSessionState.Timeout.ToString(CultureInfo.InvariantCulture));
}
#endif
if (_rqItem.Timeout != _rqSessionState.Timeout) {
_rqItem.Timeout = _rqSessionState.Timeout;
} s_sessionEverSet = true;
setItemCalled = true;
_store.SetAndReleaseItemExclusive(_rqContext, ReleaseStateGetSessionID(), _rqItem, _rqLockId, _rqSessionStateNotFound);
}
else {
// Can't save it because of various reason. Just release our exclusive lock on it.
Debug.Trace("SessionStateOnReleaseState", "Release exclusive lock on session, SessionId=" + _rqId); if (!_rqSessionStateNotFound) {
Debug.Assert(_rqItem != null, "_rqItem cannot null if it's not a new session");
_store.ReleaseItemExclusive(_rqContext, ReleaseStateGetSessionID(), _rqLockId);
}
}
}
#if DBG
else {
Debug.Trace("SessionStateOnReleaseState", "Session is read-only, ignoring SessionId=" + _rqId);
}
#endif Debug.Trace("SessionStateOnReleaseState", "Returning from SessionStateModule::OnReleaseState");
} if (_rqAddedCookie && !setItemCalled && context.Response.IsBuffered()) {
_idManager.RemoveSessionID(_rqContext);
} }
finally {
RestoreImpersonation();
} // WOS 1679798: PERF: Session State Module should disable EndRequest on successful cleanup
bool implementsIRequiresSessionState = context.RequiresSessionState;
if (HttpRuntime.UseIntegratedPipeline
&& (context.NotificationContext.CurrentNotification == RequestNotification.ReleaseRequestState)
&& (s_canSkipEndRequestCall || !implementsIRequiresSessionState)) {
context.DisableNotifications(RequestNotification.EndRequest, /*postNotifications*/);
_acquireCalled = false;
_releaseCalled = false;
ResetPerRequestFields();
}
}

其中主要的code是:

 else if (_rqSessionState.IsAbandoned) {
Debug.Trace("SessionStateOnReleaseState", "Removing session due to abandonment, SessionId=" + _rqId); if (_rqSessionStateNotFound) {
// The store provider doesn't have it, and so we don't need to remove it from the store. // However, if the store provider supports session expiry, and we have a Session_End in global.asax,
// we need to explicitly call Session_End.
if (_supportSessionExpiry) {
if (delayedSessionState) {
Debug.Assert(s_allowDelayedStateStoreItemCreation, "s_allowDelayedStateStoreItemCreation");
Debug.Assert(_rqItem == null, "_rqItem == null"); InitStateStoreItem(false /*addToContext*/);
} _onEndTarget.RaiseSessionOnEnd(ReleaseStateGetSessionID(), _rqItem);
}
}
else {
Debug.Assert(_rqItem != null, "_rqItem cannot null if it's not a new session"); // Remove it from the store because the session is abandoned.
_store.RemoveItem(_rqContext, ReleaseStateGetSessionID(), _rqLockId, _rqItem);
}
}

if (_rqAddedCookie && !setItemCalled && context.Response.IsBuffered()) {
_idManager.RemoveSessionID(_rqContext);
}

_rqAddedCookie 一般情况下为false,所以SessionID 默认也就没有被移除。也就是调用Abandon方法默认Session ID是不会改变的。 _onEndTarget.RaiseSessionOnEnd(ReleaseStateGetSessionID(), _rqItem);就是调用我们的Session_End方法。看到这里大家应该知道什么情况调用Session_End,什么有调用 _store.RemoveItem(_rqContext, ReleaseStateGetSessionID(), _rqLockId, _rqItem); 还有后面   _store.SetAndReleaseItemExclusive(_rqContext, ReleaseStateGetSessionID(), _rqItem, _rqLockId, _rqSessionStateNotFound);这个方法也很重要哦, 就是保存我们的Session大家可以参考 asp.net mvc Session RedisSessionStateProvider锁的实现

Session.Abandon和Session.Clear的实现和区别的更多相关文章

  1. Session.Abandon和Session.Clear有何不同 (转)

    Session.Clear()就是把Session对象中的所有项目都删除了, Session对象里面啥都没有.但是Session对象还保留.Session.Abandon()就是把当前Session对 ...

  2. Session.Abandon与Session.Clear之间的区别

    Session.Clear()就是把Session对象中的所有项目都删除了,Session对象里面什么都没有.但是Session对象还保留. Session.Abandon()就是把当前Session ...

  3. Session.Abandon, Session.Clear和Session.Remove的区别

    Session.Clear()就是把Session对象中的所有项目都删除了, Session对象里面啥都没有.但是Session对象还保留. Session.Abandon()就是把当前Session ...

  4. HttpContext.Current.Session.Abandon() 大坑 要注意

    HttpContext.Current.Session.Abandon(); 如果在调用以上代码之后再存储session 在当前上下文之内是可以访问session的.. 但是页面跳转之后..在其他页面 ...

  5. session.flush()与session.clear()的区别及使用环境

    [From] http://blog.csdn.net/leidengyan/article/details/7514484 首先session是有一级缓存的,目的是为了减少查询数据库的时间,提高效率 ...

  6. session.flush()与session.clear()的区别

    session.flush()和session.clear()就针对session的一级缓存的处理. 简单的说, 1 session.flush()的作用就是将session的缓存中的数据与数据库同步 ...

  7. [原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. asp.net(C#)清除全部Session与单个Session

    Session.Abandon();//清除全部SessionSession["UserName"] = null;Session.Remove("UserName&qu ...

  9. [Session] SessionHelper---C#操作Session的帮助类 (转载)

    点击下载 SessionHelper.rar 下面是代码大家看一下 这个类主要是关于Session的基本操作比如:1.获取Session值2.设置一个Session的值3.清空所有的Session4. ...

随机推荐

  1. LeetCode(31): 下一个排列

    Medium! 题目描述: (请仔细读题) 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列) ...

  2. hdu4812 逆元+树分治

    逆元链接:https://www.cnblogs.com/zzqc/p/7192436.html 经典的树分治题 #pragma comment("linker,"/STACK:1 ...

  3. 性能测试十七:liunx下jmeter结果报表、html报表

    控制台日志,只能看出整体的数据,若只是测单接口,这个最好用,但若有多个接口时,无法分别展示,所以需要换另外一种报表 四种方式来获取Jmeter的结果报表 一.在GUI模式下跑Jmeter的脚本,用tp ...

  4. python 全栈开发,Day114(装饰器,排序规则,显示列,添加按钮,定制ModelForm,自定义列表页面,自定制URL)

    一.装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务处理, ...

  5. tomcat启动慢解决方案

    一.环境 centos6.7  tomcat8    jdk1.8 二.现象 启动tomcat会花费10多分钟,正常情况下几秒就可以了. 三.解决办法 度娘了一下是因为jdk在生成随机数上耗时,找到j ...

  6. 深入了解Activiti工作流流程定义

    深入了解Activiti工作流流程定义 2016-03-27| 发布: | 浏览: 2363 |保存PDF 部署流程定义 部署流程定义的流程: 1. 先获取流程引擎对象:在创建时会自动加载 class ...

  7. MT4编程初级手册

    http://www.fxunion.com/college/2015/17554.html

  8. BZOJ1303 [CQOI2009]中位数图 其他

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1303 题意概括 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数 ...

  9. Linux系统之常用文件搜索命令

    (一)常用文件搜索命令 (1)which命令 (2)find命令 (3)locate (4)updatedb (5)grep (6)man (7)whatis (一)常用文件搜索命令 (1)which ...

  10. 不一样的go语言之入门篇-Hello World

      这是<不一样的go语言>的开篇之作,我尝试以java语言转变者的角度来聊一聊go语言.所以今天先从go语言的基础开始,即语法.   学习一门新的编程语言,必从语法开始.但需要注意的是, ...