Asp.Net MVC頁面靜態化功能實現一:利用IHttpModule,摒棄ResultFilter


上一篇有提到利用IHttpModule和ResultFilter實現頁面靜態化功能。后來經過一些改動,將ResultFilter中要實現的功能全部轉移到IHttpModule中來實現

Asp.Net MVC頁面靜態化功能實現一:利用IHttpModule和ResultFilter

1、改動后的自定義IHttpModule實現代碼:

public class RouterHttpModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += this.Application_BeginRequest; //注冊事件
    }

    private void Application_BeginRequest(Object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        string filePath = context.Request.FilePath;
        string fileExtension = VirtualPathUtility.GetExtension(filePath);
        //如果當前請求的不是資源文件、不是后台管理、請求中沒有表單信息、靜態頁面存在,則返回靜態頁面
        if (string.IsNullOrEmpty(fileExtension) && !filePath.ToLower().StartsWith("/admin") && context.Request.Form.Count.Equals(0))
        {
            string htmlPath = context.Request.HtmlFilePath();
            if (File.Exists(htmlPath))
            {
                context.Response.WriteFile(htmlPath);
                context.Response.End();
            }
            context.Response.Filter = new HttpResponseFilterWrapper(context.Response.Filter, context);
        }
    }

    public void Dispose() { }
}

這里只是在判斷靜態頁面文件是否存在之后加了這樣一段代碼:context.Response.Filter = new HttpResponseFilterWrapper(context.Response.Filter, context);

 

2、HttpResponseFilterWrapper的實現代碼

HttpResponseFilterWrapper的功能還跟以前一樣,保存Filter中返回給客戶端的html代碼到服務器硬盤上

public class HttpResponseFilterWrapper : Stream
{
    private Stream inner;
    private HttpContext context;
    public HttpResponseFilterWrapper(System.IO.Stream s, HttpContext context)
    {
        this.inner = s;
        this.context = context;
    }

    public override bool CanRead
    {
        get { return inner.CanRead; }
    }

    public override bool CanSeek
    {
        get { return inner.CanSeek; }
    }

    public override bool CanWrite
    {
        get { return inner.CanWrite; }
    }

    public override void Flush()
    {
        inner.Flush();
    }

    public override long Length
    {
        get { return inner.Length; }
    }

    public override long Position
    {
        get{ return inner.Position; }
        set{ inner.Position = value; }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return inner.Read(buffer, offset, count);
    }

    public override long Seek(long offset, System.IO.SeekOrigin origin)
    {
        return inner.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        inner.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        if (!context.Response.StatusCode.Equals(200))
        {
            return;
        }
        inner.Write(buffer, offset, count);
        //if (!context.HttpContext.Request.FilePath.ToLower().StartsWith("/admin"))
        //當前請求不是后台管理;並且返回客戶端是html才生成靜態頁面
        if (!context.Request.FilePath.ToLower().StartsWith("/admin") && context.Response.ContentType.Equals("text/html"))
        {
            //靜態頁面保存路徑信息
            string htmlPath = context.Request.HtmlFilePath();
            string direcHtmlPath = Path.GetDirectoryName(htmlPath);  
            if (!Directory.Exists(direcHtmlPath))
            {
                Directory.CreateDirectory(direcHtmlPath);
            }
            //獲取返回客戶端的html代碼,並進行壓縮處理
            string htmlCode = System.Text.Encoding.UTF8.GetString(buffer); 
            string isZipHtml = WebConfigInfo.GetConfigValueByKey("IsCompressed");
            //如果“IsCompressed”的值為空或0,則表示不壓縮
            if (!string.IsNullOrEmpty(isZipHtml) && !isZipHtml.Equals(0))
            {
                htmlCode = Regex.Replace(htmlCode, "^\\s*", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
                htmlCode = Regex.Replace(htmlCode, "\\r\\n", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
                htmlCode = Regex.Replace(htmlCode, "<!--*.*?-->", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
            }
            //保存文件,這里不能用File.WriteAllText
            File.AppendAllText(htmlPath, htmlCode);
        }
    }
}

 

3、確保靜態頁面數據的及時性

當在后台管理系統中,對某個欄目或某篇文章進行過增刪改的操作時,要同時保證靜態頁面中的數據與數據庫中的數據保持一致。

最初想到的實現方法是在靜態頁面中設定一個過期時間,但是公司所使用的框架中內容信息是通過異步加載進來的,所以保存的靜態頁面中不存<html><head><body>標簽,所以就放棄了這種方法。因為項目時間關系,最后偷了一點懶,在后台管理中添加一個“重新發布”的功能,直接將之前生成的靜態頁面全部刪除掉。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM