三、OutputCache 编程方式输出页面缓存
ASP.NET内置的 OutputCache 缓存可以将内容缓存在三个地方:Web服务器、代理服务器和浏览器。当用户访问一个被设置为 OutputCache的页面时,ASP.NET在MSIL之后,先将结果写入output cache缓存,然后在发送到浏览器,当用户访问同一路径的页面时,ASP.NET将直接发送被Cache的内容,而不经过.aspx编译以及执行MSIL的过程,所以,虽然程序的本身效率没有提升,但是页面载入速度却得到了提升。
为了实现这个功能,我们继续改写上面的 Application_BeginRequest 事件,我们在 TransmitFile 后,将这个路径的页面以OutputCache编程的方式缓存起来:
private void Application_BeginRequest( object sender, EventArgs e ) {
//.............
if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
response.TransmitFile( path );
// 添加 OutputCache 缓存头,并缓存在客户端
response.Cache.SetExpires( DateTime.Now.AddMinutes( 5 ) );
response.Cache.SetCacheability( HttpCacheability.Public );
response.End();
return;
}
//............
}
//.............
if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
response.TransmitFile( path );
// 添加 OutputCache 缓存头,并缓存在客户端
response.Cache.SetExpires( DateTime.Now.AddMinutes( 5 ) );
response.Cache.SetCacheability( HttpCacheability.Public );
response.End();
return;
}
//............
}
四、实现CommonFilter类过滤ViewState、过滤NamingContainer、空白字符串,以及生成磁盘的缓存文件
我们传入response.Filter的Stream对象给CommonFilter类:
首先,我们用先Stream的Write方法实现生成磁盘的缓存文件,代码如下,在这些代码中,只有初始化构造函数,Write方法,Close方式是有用的,其中FileStream字段是生成静态文件的操作对象:
namespace ASPNET_CL.Code.HttpModules {
public class CommonFilter : Stream {
private readonly Stream _responseStream;
private readonly FileStream _cacheStream;
public override bool CanRead {
get {
return false;
}
}
public override bool CanSeek {
get {
return false;
}
}
public override bool CanWrite {
get {
return _responseStream.CanWrite;
}
}
public override long Length {
get {
throw new NotSupportedException();
}
}
public override long Position {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
public CommonFilter( Stream responseStream, FileStream stream ) {
_responseStream = responseStream;
_cacheStream = stream;
}
public override long Seek( long offset, SeekOrigin origin ) {
throw new NotSupportedException();
}
public override void SetLength( long length ) {
throw new NotSupportedException();
}
public override int Read( byte[] buffer, int offset, int count ) {
throw new NotSupportedException();
}
public override void Flush() {
_responseStream.Flush();
_cacheStream.Flush();
}
public override void Write( byte[] buffer, int offset, int count ) {
_cacheStream.Write( buffer, offset, count );
_responseStream.Write( buffer, offset, count );
}
public override void Close() {
_responseStream.Close();
_cacheStream.Close();
}
protected override void Dispose( bool disposing ) {
if ( disposing ) {
_responseStream.Dispose();
_cacheStream.Dispose();
}
}
}
}
public class CommonFilter : Stream {
private readonly Stream _responseStream;
private readonly FileStream _cacheStream;
public override bool CanRead {
get {
return false;
}
}
public override bool CanSeek {
get {
return false;
}
}
public override bool CanWrite {
get {
return _responseStream.CanWrite;
}
}
public override long Length {
get {
throw new NotSupportedException();
}
}
public override long Position {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
public CommonFilter( Stream responseStream, FileStream stream ) {
_responseStream = responseStream;
_cacheStream = stream;
}
public override long Seek( long offset, SeekOrigin origin ) {
throw new NotSupportedException();
}
public override void SetLength( long length ) {
throw new NotSupportedException();
}
public override int Read( byte[] buffer, int offset, int count ) {
throw new NotSupportedException();
}
public override void Flush() {
_responseStream.Flush();
_cacheStream.Flush();
}
public override void Write( byte[] buffer, int offset, int count ) {
_cacheStream.Write( buffer, offset, count );
_responseStream.Write( buffer, offset, count );
}
public override void Close() {
_responseStream.Close();
_cacheStream.Close();
}
protected override void Dispose( bool disposing ) {
if ( disposing ) {
_responseStream.Dispose();
_cacheStream.Dispose();
}
}
}
}