文章教程

第11章ASP.NET缓存机制

8/31/2020 9:10:17 PM 人评论 次浏览

第11章 ASP.NET缓存机制

本章视频教学录像:18分钟

缓存是系统或应用程序将频繁使用的数据保存到内存中,当系统或应用程序再次使用时,能够快速地获取数据。缓存技术是提高Web应用程序开发效率的最常用的技术。在ASP.NET中,有三种Web应用程序可以使用缓存技术,即页面输出缓存、页面部分缓存和页面数据缓存,本章将分别介绍这三种缓存技术。

本章要点(已掌握的在方框中打钩)

□ 了解ASP.NET缓存

□ 页面输出缓存

□ 页面部分缓存

□ 页面数据缓存

11.1 ASP.NET缓存概述

本节视频教学录像:3分钟

缓存是ASP.NET中非常重要的一个特性,可以生成高效能的Web应用程序。生成高效能的Web应用程序最重要的因素之一,就是将那些频繁访问、而且不需要经常更新的数据存储在内存中,当客户端再一次访问这些数据时,可以避免重复获取满足先前请求的信息,实现快速显示请求的Web页面。

ASP.NET 4.0中有3种Web应用程序可以使用缓存技术,即页面输出缓存、页面部分缓存和页面数据缓存。ASP.NET 4.0的缓存功能具有以下优点:

1. 支持更为广泛和灵活的可开发特性

ASP.NET4.0包含一些新增的缓存控件和API。例如,自定义缓存依赖、Substitution控件、页面输出缓存API等,这些特征能够明显改善开发人员对于缓存功能的控制。

2. 增强可管理性

使用ASP.NET4.0提供的配置和管理功能,可以更加轻松地管理缓存功能。

3. 提供更高的性能和可伸缩性

ASP.NET4.0提供了一些新的功能,例如SQL数据缓存依赖等,这些功能帮助开发人员创建高性能、伸缩性强的Web应用程序。

当然除此之外,缓存功能也有自身的不足,比如显示的内容可能不是最新、最准确的,为此必须设置合适的缓存策略。又如,缓存增加了系统的复杂性并使其难于测试和调试,因此建议在没有缓存的情况下开发和测试应用程序,然后在性能优化阶段启用缓存选项。

如果不设置缓存,ASP.NET会根据每个请求重复n次,这就增加了不必要的开销。所以,可能的情况下尽量使用缓存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提高应用程序的性能。毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络连接的数据库查询操作等。

11.2 页面缓存

本节视频教学录像:11分钟

本节介绍页面缓存的相关内容。

11.2.1 页面输出缓存

页面输出缓存是最为简单的缓存机制,该机制将整个ASP.NET页面内容保存在服务器内存中。当用户请求该页面时,系统从内存中输出相关数据,直到缓存数据过期。在这个过程中,缓存内容直接发送给用户,而不必再次经过页面处理生命周期。通常情况下,页面输出缓存对于那些包含不需要经常修改内容的,但需要大量处理才能编译完成的页面特别有用。需要读者注意的是,页面输出缓存是将页面全部内容都保存在内存中,并用于完成客户端请求。

页面输出缓存需要利用有效期来对缓存区中的页面进行管理。设置缓存的有效期可以使用@OutputCache指令。@OutputCache指令如下:

<% @ OutputCache Duration="#ofseconds"

Location="Any | Client | Downstream | Server | None | ServerAndClient "

Shared="True | False"

VaryByControl="controlname"

VaryByCustom="browser | customstring"

VaryByHeader="headers"

VaryByParam="parametername"

%>

@OutputCache指令中的各个属性的说明如下:

⑴Duration:页或用户控件进行缓存的时间(以秒计)。在页或用户控件上设置该属性为来自对象的 HTTP 响应建立了一个过期策略,并将自动缓存页或用户控件输出。该属性是必须的。

⑵Location:用于指定输出缓存项的位置。其属性值是OutputCacheLocation枚举值,它们是Any、Client、Downstream、None、Server和ServerAndClient。默认值是Any,表示输出缓存可用于所有请求,包括客户端浏览器、代理服务器或处理请求的服务器上。需要注意的是,包含在用户控件中的@ OutputCache指令不支持此属性。

⑶Shared:一个布尔值,确定用户控件输出是否可以由多个页共享。默认值为False。

⑷VaryByControl:该属性使用一个分号分隔的字符串列表来更改用户控件的输出缓存。这些字符串代表在用户控件中声明的ASP.NET服务器控件的ID属性值。除非已经包含了VaryByParam属性,否则在@ OutputCache指令中,该属性是必需的。

⑸VaryByCustom:用于自定义输出缓存要求的任意文本。如果赋予该属性值是browser,缓存将随浏览器名称和主要版本信息的不同而异。如果输入了自定义字符串,则必须在应用程序的Global. asax文件中重写HttpApplication.GetVaryByCustomString方法。

⑹VaryByHeader:该属性中包含由分号分隔的HTTP标头列表,用于使输出缓存发生变化。当将该属性设为多标头时,对于每个指定的标头,输出缓存都包含一个请求文档的不同版本。VaryByHeader属性在所有HTTP 1.1缓存中启用缓存项,而不仅限于ASP.NET缓存。

⑺VaryByParam:该属性定义了一个分号分隔的字符串列表,用于使输出缓存发生变化。默认情况下,这些字符串与用GET方法属性发送的查询字符串值对应,或与用POST方法发送的参数对应。当将该属性设置为多参数时,对于每个指定的参数,输出缓存都包含一个请求文档的不同版本。可能的值包括“none”、“*”和任何有效的查询字符串或POST参数名称。

【范例11-1】设置页面缓存的过期时间为当前时间加上60秒。

程序实现的主要步骤如下:

⑴新建ASP.NET空网站PageOutputCache,添加页面并采用默认名称。

⑵将Default.aspx页面切换到HTML视图中,在<%@ Page%>指令的下方添加如下代码,实现页面缓存的过期时间为当前的时间加上60秒:

<% @ OutputCache Duration ="60" VaryByParam ="none"%>

⑶双击页面打开Default.aspx.cs页面,添加如下代码,输出当前的系统时间,用于比较程序在60秒内和60秒后的运行状态。

01 void Page_Load(object sender,EventArgs e)

02 {

03 Response.Write("页面缓存设置示例:<br>设置缓存时间为60秒,当前时间为:" + DateTime.Now.ToString());

04 }

【运行结果】

按【Ctrl+F5】组合键运行,测试运行结果,如图所示。程序运行60秒内刷新页面,页面中的数据不发生变化;60秒后刷新页面,页面中的数据发生变化。

figure_0303_0548

11.2.2 页面局部缓存

本节介绍页面局部缓存的相关内容。

1. 页面输出缓存概述

通常情况下,缓存整个页面是不合理的,因为页的某些部分在每一次请求都进行更改,这种情况下,只能缓存页的一部分即页面部分缓存。页面部分缓存是将页面的部分内容保存在内存中以便响应用户请求,而页面其他部分内容则为动态内容。页面部分缓存的信息包含在一个用户控件内,然后将该用户控件标记为可缓存的,以此来缓存页面输出的部分内容。片段缓存,也就是控件缓存,这一方式缓存了页面的特定内容,而没有缓存整个页面,因此,每次都需要重新创建整个页。而另外一种方式,替换后缓存与用户控件缓存正好相反。这种方式缓存整个页,但页中的各段都是动态的。

设置控件缓存的实质是对用户控件进行缓存配置。主要包括以下3种方法。

⑴使用@ OutputCache指令以声明方式为用户控件设置缓存功能。

⑵在代码隐藏文件中使用PartialCachingAttribute类设置用户控件缓存。

⑶使用ControlCachePolicy类以编程方式指定用户控件缓存设置。

2. 使用@ OutputCache指令设置用户控件缓存功能

@ OutputCache指令以声明方式为用户控件设置缓存功能,用户控件缓存与页面输出缓存的@ OutputCache指令设置方法基本相同,都在文件顶部设置@ OutputCache指令。不同点包括如下两个方面。

⑴用户控件缓存功能的 @ OutputCache 指令设置在用户控件文件内,而页面输出缓存的@ OutputCache指令设置在普通ASP.NET文件中。

⑵用户控件缓存的@ OutputCache指令只能设置6个属性,即Duration、Shared、SqlDependency、VaryByControl、VaryByCustom和VaryByParam。而在页面缓存的@ OutputCache指令字符串设置的属性多达10个。

用户控件中的@ OutputCache指令设置源代码如下:

<% @ OutputCache Duration ="60" VaryByParam ="none" VaryByControl =“ControlID”%>

以上代码为用户控件中的服务器控件设置缓存,其中缓存时间为60秒,ControlID是服务器控件ID属性值。

3. 使用PartialCachingAttribute类设置用户控件缓存功能

使用PartialCachingAttribute类可以在用户控件(.ascx文件)中设置有关控件缓存的配置内容。PartialCachingAttribute类包含六个常用属性和四个类构造函数,其中六个常用属性与@OutputCache指令设置的六个属性完全相同,只是使用方式不同,这里不再赘述。下面重点介绍PartialCachingAttribute类中的构造函数,PartialCachingAttribute类的四种构造函数如下:

⑴[PartialCaching(int duration)]。

这是最为常用的一种格式。其参数duration为整数类型,用于设置用户控件缓存有效期时间值。该参数与@ OutputCache指令中的Duration属性对应。

⑵[PartialCaching(int duration, string varyByParams, string varyByControls, string varyByCustom)]。

这种格式设置的内容较多。参数duration与上面说明的相同。参数varyByParams是一个由分号分隔的字符串列表,用于使输出缓存发生变化。该参数与@OutputCache指令中的VaryByParam属性对应。参数varyByControls是一个由分号分隔的字符串列表,用于使输出缓存发生变化,其与@OutputCache指令中的VaryByControl属性对应。参数varyByCustom用于设置任何表示自定义输出缓存要求的文本,与@OutputCache指令中的VaryByCustom属性对应。

⑶[PartialCaching(int duration, string varyByParams, string varyByControls, string varyByCustom, bool shared)]。

这种格式中,参数duration、varyByParams、varyByControls、varyByCustom都与上面说明的参数相同。只有参数shared是新添加的。参数shared值是一个布尔值,用于确定用户控件输出缓存是否可以由多个页面共享。默认值为false。当该参数设置为true,表示用户控件输出缓存可以被多个页面共享,可以潜在节省大量内存。

⑷[PartialCaching(int duration, string varyByParams, string varyByControls, string varyByCustom, string sqlDependency, bool shared)]。

以上格式中添加了一个新参数sqlDependency。用于设置用户控件缓存入口所使用SQL Server缓存依赖功能的数据库及表名。如果包含多个数据库及表名,则使用分号(;)分隔开来。当该属性值发生变化时,缓存入口将过期。另外,数据库名必须与web.config文件中的<sqlcachedependency>配置节的内容匹配。

以上介绍了PartialCachingAttribute类的六个属性和四种构造函数。下面通过一个典型示例说明该类的具体应用方法。

【范例11-2】使用PartialCachingAttribute类实现设置用户控件缓存。

⑴新建ASP.NET空网站命名为PartialCachingAttribute,添加默认主页Default.aspx,并在该页中添加一个Label控件用于显示当前系统时间。因此在Default.aspx.cs的Page_Load()事件中输入以下代码:

01 protected void Page_Load(object sender, EventArgs e)

02 {

03  this.Label1.Text= "Web页中的系统时间:"+DateTime.Now.ToString();

04 }

⑵在项目名称上点击右键,选择【添加新项】figure_0305_0549【web用户控件】,默认名为WebUserControl.ascx,并在该用户控件中添加一个Label控件用于显示当前的系统时间。

⑶为了使用PartialCachingAttribute类设置用户控件(WebUserControl.ascx文件)的缓存有效期为20秒,必须在用户控件类声明前设置“[PartialCaching(20)]”。代码如下:

01 [PartialCaching(20)]

02 public partial class _Default :System.Web.UI.Page

03 {

04 protected void Page_Load(object sender,EventArgs e)

05 {

06   this.Label1.Text= "用户控件中的系统时间:"+DateTime.Now.ToString();

07 }

08 }

【运行结果】

按【Ctrl+F5】组合键运行,示例运行结果如图所示,示例运行20秒内刷新,运行结果中用户控件中的系统时间不变,但是Web页中的系统时间仍然变化;运行20秒后刷新页面,用户控件和Web页中的系统时间都会发生变化。

figure_0305_0550
figure_0305_0551
figure_0305_0552

4. 使用ControlCachePolicy

ControlCachePolicy是.NET Framework 2.0中新增的类,主要用于提供对用户控件的输出缓存设置的编程访问。ControlCachePolicy类包含6个属性,分别是Cached、Dependency、Duration、SupportsCaching、VaryByControl和VaryByParams。

⑴Cached:用于获取或者设置一个布尔值,表示是否在用户控件中启用控件缓存功能。true表示启用控件缓存功能,否则为false。

⑵Dependency:用于获取或者设置一个CacheDependency实例对象,该对象与用户控件的输出缓存关联。默认值为null。当CacheDependency实例对象失效时,用户控件的输出缓存将从缓存中移除。

⑶Duration:获取或者设置一个TimeSpan结构,表示用户控件输出缓存的有效时间。默认值为Zero。

⑷SupportsCaching:该属性获取一个布尔值,用于表示用户控件是否支持缓存功能。如果属性值为true,则表示该用户控件支持缓存;否则为false。

⑸VaryByControl:用于获取或者设置一个由分号分隔的字符串列表,这些字符串包含在用户控件中声明的服务器控件ID属性值。用户控件可根据该属性值,使输出缓存发生变化。

⑹VaryByParams:用于获取或者设置一个由分号分隔的字符串列表。默认情况下,这些字符串与用GET方法属性发送的查询字符串值对应,或与用POST方法发送的参数对应。用户控件可根据该属性值,使输出缓存发生变化。

下面通过一个例子说明该类的具体应用方法。

【范例11-3】使用ControlCachePolicy类实现设置用户控件缓存。

下面的示例主要演示如何在运行时动态加载用户控件,如何以编程方式设置用户控件缓存过期时间为20秒,以及如何使用绝对过期策略。

程序实现的主要步骤为:

⑴新建ASP.NET空网站并命名为PartialCachingAttribute,添加默认主页Default.aspx,并在该页中添加一个Label控件用于显示当前系统时间。

⑵在项目名称上单击右键,选中【添加新项】figure_0306_0553【web用户控件】命令,默认名为WebUserControl.ascx,并在该用户控件中添加一个Label控件用于显示当前的系统时间。

⑶使用PartialCachingAttribute类设置用户控件(WebUserControl.ascx文件)的默认缓存有效期为80秒。代码如下:

01 [PartialCaching(80)]

02 public partial class WebUserControl :System.Web.UI.UserControl

03 {

04 protected void Page_Load(object sender,EventArgs e)

05  {

06  Label1.Text= "用户控件中的系统时间:"+DateTime.Now.ToLongTimeString();

07  }

08 }

⑷在 Default.aspx 页面中的 Page_Init 事件下动态加载用户,并使用 SetSlidingExpitation 和SetExpires方法更改用户控件的缓存过期时间为20秒,Page_Init事件的代码如下:

01 protected void Page_Init(Object sender,EventArgs e)

02  {

03  this.Label1.Text= "Web页中的系统时间:"+DateTime.Now.ToLongTimeString();

04 PartialCachingControlpcc= LoadControl("WebUserControl.ascx") asPartialCachingControl;

05   if (pcc.CachePolicy.Duration> TimeSpan.FromSeconds(60))

06  {

07  pcc.CachePolicy.SetExpires(DateTime.Now.Add(TimeSpan.FromSeconds(20)));

08  pcc.CachePolicy.SetSlidingExpiration(false);

09  }

10 Controls.Add(pcc);

11 }

【运行结果】

按【Ctrl+F5】组合键运行,执行程序。示例运行结果如图所示,示例运行10秒后刷新页面,运行结果中用户控件中的系统时间不变,但是Web页中的系统时间仍然变化;运行20秒后刷新页面,用户控件和Web页中的系统时间都会发生变化。读者会发现整个过程中中间的用户控件中的系统时间保持不变,这是因为这个缓存有效期是由初次加载时的默认缓存有效期决定的,而初次加载时默认缓存有效期大于20秒,因此,20秒内这个时间是不会有变化的。

示例运行初期:

figure_0307_0554

12秒后刷新:

figure_0307_0555

20秒后刷新:

figure_0307_0556

11.2.3 页面数据缓存

页面数据缓存即应用程序数据缓存,它提供了一种编程方式,可通过键/值将任意数据存储在内存中。使用应用程序缓存与使用应用程序状态类似,但是与应用程序状态不同的是,应用程序数据缓存中的数据是容易丢失的,即数据并不是在整个应用程序生命周期中都存储在内存中。应用程序数据缓存的优点是由ASP.NET管理缓存,它会在项过期、无效或内存不足时移除缓存中的项,还可以配置应用程序缓存,以便在移除项时通知应用程序。

ASP.NET中提供了类似于Session的缓存机制,即页面数据缓存。利用页面数据缓存,可以在内存中存储各种与应用程序相关的对象。对于各个应用程序来说,数据缓存只是在应用程序内共享,并不能在应用程序间共享。Cache类用于实现Web应用程序的缓存,在Cache中存储数据最简单的方法如下:

Cache[“Key”] = Value;

从缓存中取数据时,需要先判断一下缓存中是否有内容,另外需要注意的是从Cache中取出的是一个Object类型的对象,注意类型转换,其方法如下:

Value = (String)Cache[“key”];

If(Value != null)

{

//do something;

}

Cache类中有两个重要的方法,即Add和Insert方法,其语法格式如下:

public Object Add[Insert](

string key,

Object value,

CacheDependency dependencies,

DateTime absoluteExpiration,

TimeSpan slidingExpiration,

CacheItemPriority priority,

CacheItemRemovedCallback onRemoveCallback

)

参数说明:

⑴key

类型:SystemString

用于引用该项的缓存键。

⑵value

类型:SystemObject

要添加到缓存的项。

⑶dependencies

类型:System.Web.CachingCacheDependency

该项的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数可以设置为null 。

⑷absoluteExpiration

类型:SystemDateTime

所添加对象将到期并被从缓存中移除的时间。如果使用可调到期,则 absoluteExpiration 参数必须为NoAbsoluteExpiration。

⑸slidingExpiration

类型:SystemTimeSpan

最后一次访问所添加对象时与该对象到期时之间的时间间隔。如果该值等效于20分钟,则对象在最后一次被访问20分钟之后将到期并从缓存中移除。如果使用绝对到期,则slidingExpiration参数必须为NoSlidingExpiration。

⑹priority

类型:System.Web.CachingCacheItemPriority

对象的相对成本,由CacheItemPriority枚举表示。缓存在退出对象时使用该值;具有较低成本的对象在具有较高成本的对象之前被从缓存中移除。

⑺onRemoveCallback

类型:System.Web.CachingCacheItemRemovedCallback

在从缓存中移除对象时所调用的委托(如果提供)。当从缓存中删除应用程序的对象时,可使用它来通知应用程序。

Insert方法声明与Add方法类似,但Insert方法为可重载方法,其结构如表所示。

figure_0309_0557

在Insert方法中,CacheDependency是指依赖关系,DateTime是指有效时间,TimeSpan是创建对象的时间间隔。

下面通过几个小示例,来讲解Insert方法的使用。

例如:将文件中的XML数据插入缓存,无需在以后请求时从文件中读取。CacheDependency的作用是确保缓存在文件更改后立即到期,以便可以从文件中提取最新数据,重新进行缓存。如果缓存的数据来自若干个文件,还可以指定一个文件名的数组。代码如下:

Cache.Insert(“key”, myXMLFileData, new System.Web.Caching.CacheDependency

(Server.MapPath(“user.xml”)));

例如:插入键值为key的第二个数据块(取决于是否存在第一个数据块)。如果缓存中不存在名为key的键,或者与该键相关联的项已到期或被更新,那么dependentkey的缓存条目将到期,代码如下:

Cache.Insert(“dependenctkey”, myDependentData, new

System.Web.Caching.CacheDependency(new String[]{}, new Stirng[] {“key”}));

下面是一个绝对到期的示例,此示例将对受时间影响的数据缓存1分钟,1分钟过后,缓存将到期。其中有一点需要注意,绝对到期和滑动到期不能一起使用。

Cache.Insert(“key”, myTimeSensitiveData, null,

DateTime.Now.AddMinutes(1), TimeSpan.Zero);

下面是一个滑动到期的示例,此示例将缓存一些频繁使用的数据。数据将在缓存中一直保存下去,除非数据未被引用的时间达到了1分钟。

Cache.Insert(“key”, myFrequentlyAccessedData, null,

System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1));

11.3 高手点拨

本节视频教学录像:4分钟

1. 通过Response.Cache以编程的方式设置网页输出缓存时间

设置网页输出缓存的持续时间,可以采用编程的方式通过Response.Cache方法来实现。其使用方法如下:

Response.Cache.SetExpires(DateTime.Now.AddMinutes(20)); //20秒后移除

Response.Cache.SetExpires(DateTime.Parse(“4:00:00PM”)); //有效期到下午4点

Response.Cache.SetMaxAge(new TimeSpan(0,0,10,0)); //有效期为10分钟

2. 设置网页缓存的位置

网页缓存的位置可以根据缓存的内容来决定,比如,对于安全性要求比较高的网页,最好在Web服务器上进行缓存;对于普通网页,则可以允许在任何具有缓存功能的装置上缓存,以提高资源的使用率。

如果使用@OutputCache指令进行网页输出缓存位置的设置,可以使用Location属性。例如,设置网页只能缓存在服务器的代码如下:

<%@OutputCache Duration=”60”VaryByParam=”none”Location=”Server”%>

11.4 实战练习

1. 创建ASP.NET网站,并设置页面缓存的过期时间为当前时间加上60秒。

2. 使用11.2.2小节中提供的任意一种方法设置用户控件缓存功能,并查看用户系统时间和Web页中的系统时间对比,理解缓存的概念和实现。

教程类别