我们知道自从ASPNET 发布以来页输出缓存使开发人员能够把由网页控件及HTTP响应等生成的输出内容存储到内存中这样一来在后面的Web请求时系统能够从内存检索这些生成的输出内容而不是从头开始重新生成输出从而使ASPNET可以更迅速地提供内容在性能上得到了很大的提高但是这种方法确有一个限制即生成的内容一定要存储在内存中这样一来服务器将承受巨大流量带来的压力输出缓存消耗的内存与来自Web应用程序的其他部分的内存需求之间导致严重沖突
针对上述情况ASPNET 针对输出缓存增加了一个扩展点它能够使你可以配置一个或多个自定义输出缓存提供程序输出缓存提供程序可以使用任何的存储机制来存储HTML内容这使得开发者有可能针对不同的持久性机制来创建自定义的输出缓存提供程序其中可以包括本地或远程磁盘数据库云存储和分布式缓存引擎(如velocitymemcached)等等
要实现自定义输出缓存提供程序你可以通过从SystemWebCachingOutputCacheProvider类中派生一个类来创建自定义输出缓存提供程序例如下面的MyOutputCacheProvider类就是派生自OutputCacheProvider类并创建了一个自定义输出缓存提供程序如代码清单所示
代码清单MyOutputCacheProvidercs
using System;
using SystemCollectionsGeneric;
using SystemIO;
using SystemLinq;
using SystemRuntimeSerializationFormattersBinary;
using SystemTimers;
using SystemWebCaching;
using SystemCollectionsConcurrent;
namespace __
{
public class MyOutputCacheProvider : OutputCacheProvider
{
private Timer timer;
private string cachePath = C:\\Cache\\;
private ConcurrentDictionary<string DateTime>
cacheExpireList;
private const string KEY_PREFIX = __outputCache_;
public MyOutputCacheProvider()
{
cacheExpireList =
new ConcurrentDictionary<string DateTime>();
timer = new Timer();
timerElapsed += (o e) =>
{
var discardedList = from cacheItem in cacheExpireList
where cacheItemValue < DateTimeNow
select cacheItem;
foreach (var discarded in discardedList)
{
Remove(discardedKey);
DateTime discardedDate;
cacheExpireListTryRemove(discardedKey
out discardedDate);
}
};
timerStart();
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name=key>缓存的键</param>
/// <param name=entry>缓存的对象</param>
/// <param name=utcExpiry>过期时间</param>
/// <returns>返回缓存值</returns>
public override object Add(string key object entry
DateTime utcExpiry)
{
FileStream fs = new FileStream(
StringFormat({}{}binary cachePath key)
FileModeCreate FileAccessWrite);
BinaryFormatter formatter = new BinaryFormatter();
formatterSerialize(fs entry);
fsClose();
cacheExpireListTryAdd(key utcExpiryToLocalTime());
return entry;
}
/// <summary>
/// 获得缓存值
/// </summary>
/// <param name=key>缓存键</param>
/// <returns>缓存值</returns>
public override object Get(string key)
{
string path =
StringFormat({}{}binary cachePath key);
if (FileExists(path))
{
FileStream fs = new FileStream(
path FileModeOpen FileAccessRead);
BinaryFormatter formatter = new BinaryFormatter();
object result = formatterDeserialize(fs);
fsClose();
return result;
}
else
{
return null;
}
}
/// <summary>
/// 根据键移除缓存
/// </summary>
/// <param name=key>缓存键</param>
public override void Remove(string key)
{
string path =
StringFormat({}{}binary cachePath key);
if (FileExists(path))
{
FileDelete(path);
}
}
/// <summary>
/// 设置缓存
/// </summary>
/// <param name=key>缓存的键</param>
/// <param name=entry>缓存的对象</param>
/// <param name=utcExpiry>过期时间</param>
public override void Set(string key object entry
DateTime utcExpiry)
{
string path =
StringFormat({}{}binary cachePath key);
FileStream fs = new FileStream(
path FileModeCreate FileAccessWrite);
BinaryFormatter formatter = new BinaryFormatter();
formatterSerialize(fs entry);
fsClose();
cacheExpireListTryAdd(key utcExpiryToLocalTime());
}
}
}
在MyOutputCacheProvider类中我们重写了OutputCacheProvider类的AddGetRemove与Set方法并将页输出缓存到C:\\Cache\\文件夹里
定义好MyOutputCacheProvider类之后你可以通过使用OutputCache元素的新的providers节在nfig文件中配置提供程序如下面的示例所示
<caching>
<outputCache defaultProvider=AspNetInternalProvider>
<providers>
<add name=MyOutputCacheProvider
type=__MyOutputCacheProvider/>
</providers>
</outputCache>
</caching>
默认情况下在ASPNET 中所有的HTTP响应生成的网页以及控件都使用内存输出缓存其中defaultProvider属性被默认设置为AspNetInternalProvider当然你可以更改Web应用程序中所使用的默认的输出缓存提供程序这是通过为defaultProvider指定一个不同的提供程序名称实现的如下面的代码所示
<caching>
<outputCache defaultProvider=MyOutputCacheProvider>
<providers>
<add name=MyOutputCacheProvider
type=__MyOutputCacheProvider/>
</providers>
</outputCache>
</caching>
此外还可以针对每个控件和每个请求选择不同的输出缓存提供程序为不同的Web用户控件选择不同的输出缓存提供程序的最简单的方法就是在用户控件的指令中以声明方式使用新的ProviderName属性
下面我们将在MyOutputCacheProviderUserControl用户控件里定义该输出缓存提供程序如下面的代码所示
<%@ Control Language=C# AutoEventWireup=true
CodeBehind=MyOutputCacheProviderUserControlascxcs
Inherits=__MyOutputCacheProviderUserControl %>
<%@ OutputCache Duration= VaryByParam=none ProviderName=MyOutputCacheProvider %>
<asp:Label ID=Label runat=server />
MyOutputCacheProviderUserControlascxcs代码如下所示
public partial class MyOutputCacheProviderUserControl :SystemWebUIUserControl
{
protected void Page_Load(object sender EventArgs e)
{
thisLabelText=DateTimeNowToLongTimeString();
}
}
定义好MyOutputCacheProviderUserControl用户控件之后下面我们继续来定义一个测试页面MyOutputCacheProviderWebFormaspx代码如下所示
<%@ Page Language=C# AutoEventWireup=true
CodeBehind=MyOutputCacheProviderWebFormaspxcs
Inherits=__MyOutputCacheProviderWebForm %>
<%@ Register src=MyOutputCacheProviderUserControlascx
tagname=MyOutputCacheProviderUserControl tagprefix=uc %>
<!DOCTYPE html PUBLIC //WC//DTD XHTML Transitional//EN
transitionaldtd>
<html xmlns=>
<head runat=server>
<title></title>
</head>
<body>
<form id=form runat=server>
<div>
<asp:Button ID=Button runat=server Text=刷新页面 />
<br />
MyOutputCacheProviderUserControl
<uc:MyOutputCacheProviderUserControl ID=MyOutputCacheProviderUserControl runat=server />
<br />
MyOutputCacheProviderWebForm
<asp:Label ID=Label runat=server Text=Label></asp:Label>
</div>
</form>
</body>
</html>
MyOutputCacheProviderWebFormaspxcs代码如下所示
public partial class MyOutputCacheProviderWebForm :
SystemWebUIPage
{
protected void Page_Load(object sender EventArgs e)
{
thisLabelText=DateTimeNowToLongTimeString();
}
}
运行MyOutputCacheProviderWebFormaspx页面结果如图所示
图示例运行结果
打开C:\\Cache\\文件夹你就能够看见所生成的缓存文件如图与所示
图在本地磁盘生成的缓存文件
图缓存文件内容
这里需要注意的是你只能在用户控件中指定@ OutputCache指令的ProviderName属性但在ASPX页面是不允许你指定@ OutputCache指令的ProviderName属性的因为在页面中默认情况下会使用nfig中配置的defaultProvider
虽然你不能够以声明的方式指定@ OutputCache指令的ProviderName属性但你可以在Globalasax文件中通过重载GetOutputCacheProviderName(HttpContext context)方法以编程方式指定针对一个具体的请求使用哪一个提供程序如下面的代码所示
public override string GetOutputCacheProviderName(HttpContext context)
{
if (contextRequestPathEndsWith(MyOutputCacheProviderWebFormaspx))
{
return MyOutputCacheProvider;
}
else
{
return baseGetOutputCacheProviderName(context);
}
}
利用ASPNET 中增加的输出缓存提供程序扩展你现在可以为你的Web站点采取更积极和更智能化的输出缓存策略例如你可以把一个网站中的用户访问量占前十名的那些网页缓存到内存中而把那些较低访问量的网页缓存到磁盘上