asp.net攔截器

攔截器又稱(chēng)過(guò)濾器。

asp.net mvc本身是自帶3種攔截器:Action攔截器、Result攔截器、Exception攔截器。 應(yīng)用中常見(jiàn)的攔截器有日志攔截器(Action攔截器)和異常處理攔截器(Exception攔截器)。

java里spring mvc也常用攔截器來(lái)做些非干預(yù)業(yè)務(wù)邏輯的事,諸如實(shí)現(xiàn)HandlerInterceptor接口。

攔截器要解決的問(wèn)題:
1.代碼復(fù)用。攔截器可被復(fù)用
2.職責(zé)單一。比如廚師只負(fù)責(zé)炒菜,不管前期的洗菜、后續(xù)的送菜工作。菜變質(zhì)了也是直接喊一聲就有人來(lái)處理。

asp.net的攔截器怎么實(shí)現(xiàn)呢?
舊瓶裝新酒,asp.net的攔截器需要通過(guò)IHttpModule接口來(lái)實(shí)現(xiàn)。

這兩天重構(gòu)支付中心代碼,將設(shè)置線(xiàn)程名和IP白名單這2個(gè)功能做成攔截器。

如下是線(xiàn)程名Filter的代碼:

/// <summary>
/// 設(shè)置當(dāng)前工作線(xiàn)程的名稱(chēng)。供用來(lái)統(tǒng)一標(biāo)識(shí)記錄的日志
/// </summary>
public class ThreadNameFilter : IHttpModule
{
    LogHelperUtil logHelper = new LogHelperUtil(typeof(ThreadNameFilter).Name);

    public void Dispose()
    {
        //throw new NotImplementedException();
    }

    public void Init(HttpApplication context)
    {
        //NewMethod(context);請(qǐng)求在此上下文中不可用

        context.BeginRequest += context_BeginRequest;
    }

    /// <summary>
    /// 設(shè)置當(dāng)前工作線(xiàn)程的name
    /// </summary>
    /// <param name="sender"></param>
    private void SetThreadName(object sender)
    {

        if (null != Thread.CurrentThread.Name)
        {
            return;
        }

        HttpApplication application = (HttpApplication)sender;
        HttpRequest request2 = application.Context.Request;
        HttpResponse response = application.Context.Response;
        string url = request2.Url.LocalPath;
        url = url.Trim('/');

        // * 根據(jù)請(qǐng)求url得到一個(gè)nameFlag
        string nameFlag;
        if (url.IndexOf(".ashx", StringComparison.OrdinalIgnoreCase) > 0)
        {
            var arr = url.Split('/');
            string ashxName = arr.FirstOrDefault(str => str.IndexOf(".ashx", StringComparison.OrdinalIgnoreCase) > 0);
            nameFlag = ashxName.Substring(0, ashxName.IndexOf('.'));
            if (nameFlag == "AgentPayQuery")
            {
                nameFlag = "QueryAgentPay";
            }
        }
        else
        {
            nameFlag = url.Replace('/', '_').Replace('.', '_');
        }

        // * 設(shè)置當(dāng)前工作線(xiàn)程的name
        Thread.CurrentThread.Name = string.Format("[{0}_T{1:HHmmssfff}_{2}]", nameFlag, DateTime.Now, Guid.NewGuid().ToString().Replace("-", "").Substring(0, 5).ToUpper());
        logHelper.Write("線(xiàn)程名已設(shè)置為:{0} url:{1}", Thread.CurrentThread.Name, url);
    }

    void context_BeginRequest(object sender, EventArgs e)
    {
        SetThreadName(sender);
    }

}

接下來(lái),web.config配置此module:

可在<system.web>節(jié)點(diǎn)下的<httpModules>里配置,也可在<system.webServer>節(jié)點(diǎn)下的<modules>里配置。 這取決于應(yīng)用程序池的托管管道模式。經(jīng)典模式用前者,集成模式用后者。

本地vs2013里的iisexpress默認(rèn)是集成模式。所以,本地vs2013調(diào)試程序要在<system.webServer>里配置module。

<system.webServer>
    <modules> <!--runAllManagedModulesForAllRequests="true"-->
      <add name="threadNameFilter" type="PaymentPlatform.Filters.ThreadNameFilter" preCondition="managedHandler" />
      <add name="ipValidationInterceptor" type="PaymentPlatform.Filters.IPValidationInterceptor" preCondition="managedHandler"/> <!--只對(duì)托管資源起作用-->
    </modules> 
    <handlers>
      。。。。。。
    </handlers>
</system.webServer>

這樣,一個(gè)攔截器的開(kāi)發(fā)就完成了。

在后續(xù)的測(cè)試時(shí),出現(xiàn)了一些波折。
本地在啟動(dòng)vs2013執(zhí)行iisexpress站點(diǎn)應(yīng)用程序時(shí),發(fā)現(xiàn)明明在ThreadNameFilter 里設(shè)置了線(xiàn)程名,但觀察在后續(xù)ashx里記錄的日志里,并沒(méi)有獲取到那個(gè)線(xiàn)程名,whatever in Debug or in Release。這讓我想到之前寫(xiě)的一篇博客《巧用CurrentThread.Name來(lái)統(tǒng)一標(biāo)識(shí)日志記錄(續(xù))》,在ashx文件的默認(rèn)構(gòu)造器里設(shè)置的線(xiàn)程名,在其ProcessRequest方法的處理邏輯里也是獲取不到的。

經(jīng)多次鼓搗,才發(fā)現(xiàn),把站點(diǎn)程序發(fā)布到IIS7上之后,無(wú)論apppool的托管模式是集成(目前,集成模式是主流)還是經(jīng)典,在ThreadNameFilter 里設(shè)置的線(xiàn)程名可以被后續(xù)ashx里獲取到!
同樣,細(xì)心的觀察了一下,《巧用CurrentThread.Name來(lái)統(tǒng)一標(biāo)識(shí)日志記錄(續(xù))》里提到的問(wèn)題,發(fā)布到IIS7后也不存在,即在ashx文件的默認(rèn)構(gòu)造器里設(shè)置的線(xiàn)程名,在其ProcessRequest方法的處理邏輯里可以獲取到!

下圖是本地vs2013里訪(fǎng)問(wèn)接口所記錄的日志:

本地vs調(diào)試

下圖是發(fā)布到iis7后訪(fǎng)問(wèn)接口所記錄的日志:

發(fā)布到iis后
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,948評(píng)論 18 139
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,367評(píng)論 11 349
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,372評(píng)論 25 708
  • 你上學(xué)的時(shí)候,教室里張貼著怎樣的標(biāo)語(yǔ)呢? 我對(duì)自己中學(xué)時(shí)代的教室標(biāo)語(yǔ)毫無(wú)印象,不外乎是“團(tuán)結(jié)、奮進(jìn)”一類(lèi)...
    一斤的自?shī)首詷?lè)閱讀 765評(píng)論 1 12
  • 今年的冬天比以往還要冷,失去了多少又得到了多少,無(wú)從知曉。 山上的生活比我想象中要困難許多,陌生的地方...
    溫柔阿蘇閱讀 166評(píng)論 1 0