ASP.NET 提供了缓存技术有助于我们最大程度地解决这个问题。它能缓存输出的页面,保存在存储器当中,缓存用户请求的内容。缓存的特点可以根据不方式来定制的。
缓存一个页面
为缓存一个页面输出的内容,我们要在面面顶部指定一个 @OutputCache 命令。语法如下所示:
<%@ OutputCache Duration=5 VaryByParam="None" %>
如你所见,这条指令有两个属性。他们是:
Duration - 被缓存输出的内容有效期是多少秒。在时间超过指定的有效期后,过期的缓存内容会删除,并会在下次用户请求中重新调用页面生成缓存内容。再次的缓存内容过10秒后此过程又会重复。
VaryByParam - 这个属性是必须的,并且指明查询字串参数不同使缓存产生变化。在上面的代码片断中,我们指定 VaryByParam 属性是 “None” ,这意味着不论传递的查询字串参数如何不同所返回的页面内容是相同的。
如果对同一页面的两次请求含不同的查询字串参数,如:.../PageCachingByParam.aspx?id=12 和.../PageCachingByParam.aspx?id=15 ,这应该生成不同的页面内容,指令应该是:
<%@ OutputCache Duration=10 VaryByParam="id" %>
对这样两种不同请求的页面内容每一个都会被缓存 Duration 属性指定的时间长度。。
为了指定多个参数的情形,要使用分号来分隔参数名称。如果我们指定 VaryByParam 属性为“*”,缓存内容会因传递的不同查询字串参数而不同。
一些动态页面要根据不同的浏览来生成不同的内容。在这种情况下就要规定缓存输出内容要因不同浏览器而不同。@OutputCache 命令要改为:
<%@ OutputCache Duration=5 VaryByParam="id" VaryByCustom="browser" %>
这条指令不仅让缓存输出内容因浏览器不同而不同,而且也会因浏览器版本不同而不同,如 IE5、IE 6、Netscape 4、Netscape 6 都会获得不同输出的缓存版本。
缓存局部页面
有时我们可能只是想缓存一个页面的一小部分。例如,我们可能用这样的页面,对所有浏览用户都有同样的内容,这个页面有一个标题。这个标题可能是某个文本/图象组成,并且每天数据都可能改变。在这种情况下,我们就会只想缓存这个标题一天的有效期。
解决方法是把标题内容放入一个用户控件当中,然后指定这个用户控件应该被缓存。这个技术被称为局部缓存(fragment caching)。
为了指定应该被缓存的用户控件,我们利用 @OutputCache 指令,就象整个页面缓存的用法一样。
<%@ OutputCache Duration=10 VaryByParam="None" %>
在上面的指令中,用户控件缓存有效期是 Duration 属性指定的时间(10 秒)。不论查询字串和浏览器类型/版本如何,缓存输出的内容是相同的。。
数据缓存
ASP.NET 也支持作为对象类型数据的缓存。我们可以把对象存储在内存中,在我们应用程序的不同动态页面中使用它们。利用 Cache 类可以实现这个特点。缓存的生存周期与应用程序的相同。对象可以以键值对(name value pairs)的形式储存于缓存当中。如下所示插入一个字串进缓存:
Cache["name"]="Smitha";
这个存储的字串值可以象这样得到:
if (Cache["name"] != null)
Label1.Text= Cache["name"].ToString();
为把对象插入缓存中,可以使用 Cache 类的 Add 方法或者不同版本的 Insert 方法。这些方法可能允许我们使用这个 Cache 类提供的更强大功能,下面是利用了 Insert 方法的一个重载:
Cache.Insert("Name", strName,
new CacheDependency(Server.MapPath("name.txt"),
DateTime.Now.AddMinutes(2), TimeSpan.Zero);
头两个参数是是键名和被插入的对象。第三个参数是 CacheDependency 类型,帮我们对名为 name.txt 文件设置值的依赖项。因此一旦这个文件发生改变,在缓存中的这个值会被删除。我们可以指定 “null” 值来表明没有依赖项。第四个参数指定了从缓存删除这个值的时间。最后一个参数是缓存过期时间可调的参数,它指明了从最后一次访问缓存时间到它被删除的时间间隔。
当可用系统内存不多时,缓存自动从内存中删除使用少的项目。这个过程被称为净化(scavenging)。我们可以为添加进缓存中的项目指定优先级,以便某些项目能得到优先处理:
Cache.Insert("Name", strName,
new CacheDependency(Server.MapPath("name.txt"),
DateTime.Now.AddMinutes(2), TimeSpan.Zero,
CacheItemPriority.High, null);
枚举类型 CacheItemPriority 给成员设置不同的优先级。CacheItemPriority.High 给项目分配了个高优先级,以使该项目减少被缓存删除的可能性。
要点
如果你还是老的 ASP 页面并且利用 Response.Expires 属性缓存页面输出,那么他们也可以象 ASP.NET 支持这个属性一样被保留。
Cache 类的 Insert 方法会用相同键名的项目覆盖任何已存在项目。
CacheItemPriority.NotRemovable 优先值可以与 Cache.Insert 方法一起用于设置一个项目的优先级,以便这个项目不会在净化期间从缓存中被删除
Asp.Net的Cache对Xml文档支持的特别好,可以用Xml文档的物理路径做为Cache的依懒项,当文档内容更改时,该对象即无效,并从缓存中移除。
string filePath = Server.MapPath("Skin.xml");
XmlDocument doc = Cache["skin"] as XmlDocument;
//Cache没有该项情况
if (doc == null)
...{
doc = new XmlDocument();
doc.Load(filePath);
//缓存键依赖项。当文档内容更改时,该对象即无效,并从缓存中移除。
CacheDependency c = new CacheDependency(filePath);
//使用可调过期,对象在最后一次被访问 30 分钟之后将过期并被从缓存中移除。
Cache.Insert("skin", doc, c
, Cache.NoAbsoluteExpiration
, TimeSpan.FromMinutes(30)
);
}
else
...{
//取出指定的子节点集
XmlNodeList nodes = doc.SelectNodes("/SkinTemplates/Skins/SkinTemplate");
foreach (XmlNode node in nodes)
...{
if (node.Attributes["SkinID"].Value == "gertrude-blue")
...{
//更改节点内容,Cache移出
node.Attributes["Skin"].Value = "更改节点内容Cache移出";
}
}
//保存改变后的文档
doc.Save(filePath);
}
有时可能需要立即更新,这里就必须手工清除一下Cache
Cache类有一个Remove方法,但该方法需要提供一个CacheKey,但整个网站的CacheKey我们是无法得知的
只能经过遍历
protected void RemoveAllCache()
{
System.Web.Caching.Cache _cache = HttpRuntime.Cache;
IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
ArrayList al = new ArrayList();
while (CacheEnum.MoveNext())
{
al.Add(CacheEnum.Key);
}
foreach (string key in al)
{
_cache.Remove(key);
}
show();
}
//显示所有缓存
void show()
{
string str = "";
IDictionaryEnumerator CacheEnum = HttpRuntime.Cache.GetEnumerator();
while (CacheEnum.MoveNext())
{
str += "缓存名<b>[" + CacheEnum.Key+"]</b><br />" ;
}
this.Label1.Text = "当前网站总缓存数:" + HttpRuntime.Cache.Count + "<br />"+str;
}