当前位置: 首页 > news >正文

【分析总结】ASP.NET中的状态管理原理

      HTTP协议是介于请求、响应的断开时网络协议,与连接式的网络协议不同,例如,与我们熟悉的TCP协议相比,客户端与服务器并没有持续的连接存在,在每一次会话之后,连接都会被断开,在下一次请求的时候客户端会重新与服务器建立连接进行会话。那么,服务器如何来跟踪客户端,在断开的轻快下,客户端又如何与服务器端保持会话呢?

      为了解决这个问题,在网站开发中,提供了大量的状态管理技术来解决这个问题,在ASP.NET中,还提供了一些专用的技术,使得我们更加轻松的完成状态管理服务。

     

      ·首先我们可以考虑form表单中提供的隐藏域。顾名思义,隐藏域就是表单中看不到的输入项,他必须配合表单使用。虽然看不到,但是,在提交表单的时候,隐藏域中得信息将随着表单一起被发送到服务器。隐藏域的使用方法如下:

<form method="post" action="hidden.aspx" id="form1">
...
<input type="hidden" id="HiddenField1" name="HiddenField1" value="DebugLZQ"/>
...
</form>

      在ASP.NET中,可以通过HiddenField这个服务器控件来生成上述的HTML,这样我们就可以在服务器上,通过面向对象的方式来获取网页中得隐藏域。

this.HiddenField1.value=this.TextBox1.Text;

      在默认轻快下,ASP.NET表单将会提交到本页面,所以,在提交表单的时候,保存在客户端隐藏域中得信息将会发送回服务器。由于轻轻参数的name将会与服务器上页面对象中隐藏域控件的id相匹配,这样,在下一次请求的时候,在服务器上,我们就可以通过隐藏域控件的属性获得上一次请求中保存在隐藏域中得值。

 

this.TextBox1.Text=this.HiddenField1.value;

      存在的问题:影藏域存在于网页中得Form表单,当页面关闭的时候,隐藏域中得信息将会丢失。所以不适合需要长期有效的状态管理。

     

      ·为了能够更加长久地保存用户会话的状态信息,Cookie被Netscape公司引入网站开发中。

      传统上,网站是基于广播模式的,也就是说,所有的用户看到的内容都是一样的,,如果对用户提供一对一的服务,就必须能够从用户的请求中去别处不同的用户。虽然通过隐藏域也能部分完成这个需求,但是,当用户关闭浏览器的时候,隐藏域中保存的信息将会丢失,不能长久保存。Cookie允许用户将自己的状态信息以名值对的形式保存在客户端。在Cookie有效的情况下,在用户每次向这个服务器发出请求的时候都会自动附加在请求中,同时还允许设置Cookie保存在客户端的时间,以便于在用户关闭浏览器之后,还能继续保存状态信息。

      在HTTP协议中,通过在服务器的回应中增加Set-Cookie的回应头,可以指示客户端保存Cookie。

      浏览器会在特殊的位置来保存Cookie的内容,Cookie的内容不会在页面上显示出来,非常适合隐藏地保存状态信息。

      在浏览器保存有Cookie的情况下,在以后的请求中,浏览器将会以请求头的形式自动附加这个Cookie中保存的信息,以名值对的形式发送到服务器。

      这样,服务器就可以获得从前保存的状态信息了。

      在ASP.NET中,服务器通过HttpCookie数据类型来处理在回应中生成Set-Cookie头和在请求中的Cookie信息的问题。

public sealed class HttpCookie

      配合HttpCookie,在HttpResponse中,通过Cookie集合属性来表示准备生成回应中Set-Cookie的HttpCookie集合。这样,在服务器上,指示客户端生成Cookie的代码如下所示:

HttpCookie cookie=new HttpCookie("DebugLZQ");
cookie.Value=this.TextBox1.Text;

this.Reponse.Cookies.Add(cookie);

      对于请求中附带的Cookie信息,HttpRequest通过其Cookies集合属性表示为对象的形式,由于浏览器的请求中可能附带有多个Cookie参数,可以通过Cookie的名字来获取对应的Cookie参数。

HttpCookie cookie=new HttpCookie("DebugLZQ");
if(cookie!=null)
{
this.Label1.Text=cookie.Value;
}

      在默认情况下创建的Cookie,将保存在浏览器的Cookie容器中,当浏览器关闭时,Cookie将一同被销毁。Cookie的Expires属性表示Cookie的过期时间。这是一个绝对过期时间,以格林威治标准时间的格式表示,到达这个时间之后,Cookie将会失效。为了能过长期使用保存在Cookie中的信息,可以将Cookie的Expires属性设置为未来的一个更长的时间,在大道这个时间之前,Cookie将一直有效。例如,可以通过如下的语句将Cookie设置保存10分钟。

cookie.Expires=DateTime.Now.AddMinutes(10.0);

      注意,如果没有设置过期时间,Cookie将会保存到浏览器关闭为止。

      可是,浏览器关闭之后,Cookie将保存在那里了?他是如何做到再次打开浏览器时,依然能够取得Cookie中的值呢?
      在设置过期时间之后,浏览器会将这个Cookie保存在一个特定的文件夹中,Cookie文件时一个文本格式的文件。根据RFC2109的描述,每个客户端最多保存300个Cookie,对于每个站点来说最多20个Cookie(实际上多数浏览器现在都比这个多,比如Firefox是50个),每个cookie最多4K,注意这里的4K根据不同的浏览器可能不是严格的4096。

     

      ·我们也可以通过在URL地址中嵌入信息来实现状态管理,由于在向服务器发出请求的时候,URL地址将作为请求的一部分发送到服务器,这样,可以从中提取出保存的信息。需要在URL地址中保存信息的时候,通过将信息以特殊的格式插入到URL地址中完成。

     

      ·使用隐藏域可以在表单中传递大量的数据,但是,直接保存在隐藏域中的信息必须是字符串形式的数据,这是HTML页面的字符性质决定的。在ASP.NET服务器端处理的是以对象为表示形式的数据,如果这些对象可以被保存以便在后继的访问中使用,将大大方便服务器端的程序设计。在ASP.NET中,提供了基于隐藏域的增加对象序列化和反序列化支持的状态管理机制,通过将服务器端的可序列化对象序列化为字符串的形式,然后,以隐藏域的形式保存在也卖弄的表单中,一般在后继的请求中发送回服务器,最后通过反序列化操作还原为原来的对象,在ASP.NET中这个技术被称为视图状态ViewState

     

      ·视图状态ViewState为开发人员带来便利,但是巨大的视图状态在服务器和浏览器之间的往返传递也带来了繁重的网络压力,有的时候我们会禁用也卖弄的视图状态来提高访问的效率。

      由于有些信息对付控件来说非常重要,所以,在禁用ViewState后,会造成有些控件功能的彻底失效,比如GridView的分页功能。从ASP.NET 2 0开始,通过控件状态来提供一种比视图状态更加安全的控件状态ControlState的管理管理机制。控件状态的使用类似于视图状态,但是,即使用户关闭视图状态之后,也会仍然有效。

      类似于视图状态的LoadViewState和SaveViewState方法,控件状态也是提供了一对这样的方法,方法名称分别为LoadControlState和SaveControlState,兵器也是在Control基类中提供。

      要使用控件状态,首先需要在也卖弄上注册需要使用的控件状态。这个工作一般在控件的Init中进行,方法的参数就是要注册的控件对象。

protected override void OnInit(EventArgs e)
{
base.OnInit(e);
page.RegisterRequiresControlState(this);
}

      然后,在控件中使用LoadViewState和SaveViewState完成控件状态的加载和保存即可。

     

      ·应用程序状态HttpApplicationState的机制是比较简单的,这是一个服务器端的全局的状态管理。因为是服务器端的全局状态管理,所以,不在涉及也卖弄和请求的处理过程,也不需要区分不同的会话或者用户。为了方便保存多个不同的状态,应用程序状态Application派生自NameObjectCollectionBase,允许用户通过一个字符串的名字来保存或提取相应的对象。

      应用程序状态管理对象可以通过上下文对象获取到,他的定义如下:

public HttpApplicationState Application{get;}

      其中,HttpApplicationState的定义如下:

public sealed class HttpApplicationState:NameObjectCollectionBase

      对于引用程序状态对象来说,由于所有的请求都可能需要访问这个对象,为了解决并发访问的问题,同时还提供了线程的同步机制,通过来同步对于这个集合的访问。

public void Lock();

public void UnLock();

      HttpApplicationState类使用AllKeys和Count属性以及Add、Clear、Get、GetKey、Remove、RemoveAt和Set方法来自动锁定和解锁。但是,如果需要对保存在全局应用程序状态中的数据进行连续多次的访问,通过显式的Lock进行加锁和UnLock进行解锁有助于提高访问效率。

      对于一个网站来说,存在一个HttpApplicationState对象管理状态,这个对象随着网站的启动而穿件,当网站关闭的时候才会释放,因此,通过Application保存的状态信息会伴随整个网站的生命周期,在不适用的时候,一定要及时释放所用的空间。

     

      ·Session是一个历史悠久的状态管理技术,从ASP时代开始,就称为了Web开发不可或缺的基本状态管理技术。

      对于无状态的HTTP来说,Session是一个服务器端的状态管理方案,这个方案的特点在于每个客户端都可以将实际的数据保存在服务器上,对于客户端的数据,会生成一个对应的唯一的key。在服务器端保存数据之后,将用于取得所保存数据的key发送到客户端。在后继的请求中,客户端将这个保存在客户端的key发送回服务器端,在服务器上通过这个key来取得相应的数据。通常,我们称这个key为SessionID。Session的工作原理如下:

      在一般轻快下,这个SessionID以Cookie的形式保存在浏览器中,在不适用Cookie的情况下,也可以将这个SessionID嵌入到访问网站的URL地址中(前面讲过)。

      在页面对象或者HttpContext对象汇总,都有一个名为Session的属性,在一次会话中,他们引用的是同一个对象,定义如下:

public HttpSessionState Session{get;}

      在Sesion中,我们通常使用下面的方法来进行状态管理:

public void Add(string name,Object value)

public void Remove(string name);

public void Clear();

public void Abandon();

      这个HttpSessionState来自于SessionStateModule。在每次请求处理过程中,HttpApplication的请求的处理管道中会检查当前请求的处理程序是否实现了接口IRequiresSessionState,如果实现的话,那么SessionStateModule将为这个请求分配HttpSessionState。

      需要注意的是,只有执行下面这样的代码片段后,才可以认为Session会话开始。

Session[“DebugLZQ”]=”some data”;

      Session字典通常包含Object类型,要向后读取数据,需要将返回的值转为为更具体的类型。

string data=Session[“DebugLZQ”] as string;

      Session_OnEnd事件标志着会话的结束,并用于执行中止该会话所需的所有清除代码。

      如果会话超时或被放弃,下次访问无状态应用程序时,其会话ID不会发生改变。进过设计后,即使会话状态过期,会话ID也能持续到浏览器会话结束。也就是说,只要浏览器实例相同,就始终使用同一个会话ID表示多个会话。

      对于Session来说,关键的问题在于Session过期指的是某个会话整个Session的过期,并不针对其中某个数据的过期,要么整个Session过期后丢弃掉,要么所有的数据都被保留下来,在每一次请求的时候都会被加载到内存中,这可能会造成内存的浪费。所以,在使用Session的时候,我们必须要谨慎选择保存的数据。

 

      ·HttpContext状态可能是所有状态管理中最简单的状态管理,也是最有效的状态管理方式,HttpContext基于HttpApplication的处理管道,由于HttpContext对象贯穿整个处理过程,所以,可以从HttpApplication处理管道的前端将状态数据传递到管道的后端,完成状态的传递任务。

      在HttpContext中通过Items属性允许我们将需要传递的数据进行存取,这个属性的定义如下:

public IDictionary items{get;}

      可以看到这是一个字典,我们可以通过键值对的形式来使用它。

 

      ·缓存管理CacheASP.NET中更加强大的状态管理。这是在 ASP.NET中唯一可以根据服务器的使用情况,动态管理内存使用的状态管理干干。允许我们针对每一个缓存的数据,单独设置数据的有效条件,使得内存的使用效率最大化。Cache属于公共的状态管理,我们通过每个缓存数据的键值字符串来区分缓存的数据(不详细解释了~)。

 

   ·Memcached是dangga.com开发的一套分布式内存对象缓存系统。Memcached是分布式的,基于网络连接(当然他也可以使用localhost)方式完成服务,本身它是一个独立于应用的程序或守护进程。

      Memcached在很多时候都是作为数据库前端Cache使用的。因为他比数据库少了很多SQL解析、磁盘操作等开销,而且它是使用内存来管理数据的,所以他可以提供比直接读取数据库更好的性能。在大型系统中,访问同样的数据时很频繁的,Memcached可以大大降低数据库压力,是系统执行效率提升。

 

      【请点击下面的“绿色通道”-“关注DebugLZQ”,与DebugLZQ一起学习进步~】

相关文章:

  • 巧用单臂
  • cocos2d-x学习笔记番外篇01:地图滚动代码
  • 【hibernate系列】hibernate的n+1问题
  • 易宝php支付
  • 看不到的“因”
  • 使用WITH提高查询效率
  • css 视图结构
  • UltraEdit批量删除空行
  • border padding margin , the difference among them
  • MATLAB概率统计函数(1)
  • hoj1058 Number Triangles
  • 五、oracle 表的管理
  • 花了500学的seo课程教程笔记公布
  • 张清:当你把写博客当做一种习惯的时候
  • 一个简陋的web站点文档安全访问
  • canvas绘制圆角头像
  • iOS 系统授权开发
  • JavaScript实现分页效果
  • leetcode46 Permutation 排列组合
  • Making An Indicator With Pure CSS
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • tab.js分享及浏览器兼容性问题汇总
  • vue-cli3搭建项目
  • 程序员该如何有效的找工作?
  • 多线程 start 和 run 方法到底有什么区别?
  • 类orAPI - 收藏集 - 掘金
  • 普通函数和构造函数的区别
  • 前端路由实现-history
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 树莓派用上kodexplorer也能玩成私有网盘
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • #QT(串口助手-界面)
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • $(selector).each()和$.each()的区别
  • (1)常见O(n^2)排序算法解析
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (Git) gitignore基础使用
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (转)iOS字体
  • (转)nsfocus-绿盟科技笔试题目
  • (转载)hibernate缓存
  • .dwp和.webpart的区别
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET Core 中的路径问题
  • .Net Core和.Net Standard直观理解
  • .net refrector
  • .net 简单实现MD5
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net6 webapi log4net完整配置使用流程
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded