zoukankan      html  css  js  c++  java
  • asp.net拦截器

    拦截器又称过滤器。

    asp.net mvc本身是自带3种拦截器:Action拦截器、Result拦截器、Exception拦截器。 应用中常见的拦截器有日志拦截器(Action拦截器)和异常处理拦截器(Exception拦截器)。

    java里spring mvc也常用拦截器来做些非干预业务逻辑的事,诸如实现HandlerInterceptor接口。

    拦截器是AOP(面向切面编程)的一种应用。

    拦截器要解决的问题:

    1.代码复用。拦截器可被复用
    2.职责单一。比如厨师只负责炒菜,不管前期的洗菜、后续的送菜工作。菜变质了也是直接喊一声就有人来处理。
     
    asp.net的拦截器怎么实现呢?
    旧瓶装新酒,asp.net的拦截器需要通过IHttpModule接口来实现。
     

    这两天重构支付中心代码,将设置线程名和IP白名单这2个功能做成拦截器。
     
    如下是线程名Filter的代码:
        /// <summary>
        /// 设置当前工作线程的名称。供用来统一标识记录的日志
        /// </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);请求在此上下文中不可用
    
                context.BeginRequest += context_BeginRequest;
            }
    
            /// <summary>
            /// 设置当前工作线程的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('/');
    
                // * 根据请求url得到一个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('.', '_');
                }
    
                // * 设置当前工作线程的name
                Thread.CurrentThread.Name = string.Format("[{0}_T{1:HHmmssfff}_{2}]", nameFlag, DateTime.Now, Guid.NewGuid().ToString().Replace("-", "").Substring(0, 5).ToUpper());
                logHelper.Write("线程名已设置为:{0} url:{1}", Thread.CurrentThread.Name, url);
            }
    
            void context_BeginRequest(object sender, EventArgs e)
            {
                SetThreadName(sender);
            }
    
        }

    接下来,web.config配置此module:

    可在<system.web>节点下的<httpModules>里配置,也可在<system.webServer>节点下的<modules>里配置。  这取决于应用程序池的托管管道模式。经典模式用前者,集成模式用后者。

    本地vs2013里的iisexpress默认是集成模式。所以,本地vs2013调试程序要在<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"/> <!--只对托管资源起作用-->
        </modules> 
        <handlers>
          。。。。。。
        </handlers>
      </system.webServer>

    这样,一个拦截器的开发就完成了。

    在后续的测试时,出现了一些波折。

    本地在启动vs2013执行iisexpress站点应用程序时,发现明明在ThreadNameFilter 里设置了线程名,但观察在后续ashx里记录的日志里,并没有获取到那个线程名,whatever in Debug or in Release。这让我想到之前写的一篇博客《巧用CurrentThread.Name来统一标识日志记录(续)》,在ashx文件的默认构造器里设置的线程名,在其ProcessRequest方法的处理逻辑里也是获取不到的

    经多次鼓捣,才发现,把站点程序发布到IIS7上之后,无论apppool的托管模式是集成(目前,集成模式是主流)还是经典,在ThreadNameFilter 里设置的线程名可以被后续ashx里获取到!

    同样,细心的观察了一下,《巧用CurrentThread.Name来统一标识日志记录(续)》里提到的问题,发布到IIS7后也不存在,即在ashx文件的默认构造器里设置的线程名,在其ProcessRequest方法的处理逻辑里可以获取到!

    下图是本地vs2013里访问接口所记录的日志:

    下图是发布到iis7后访问接口所记录的日志:

  • 相关阅读:
    Java 基础入门随笔(6) JavaSE版——数组操作
    Java 基础入门随笔(5) JavaSE版——函数重载
    Java 基础入门随笔(4) JavaSE版——程序流程控制
    Java 基础入门随笔(3) JavaSE版——逻辑运算符、位运算符
    jvm第二章(二)
    jvm第二章(一)
    jvm第一章(三)
    jvm第一章(二)
    jvm第一章(一)
    Java程序初始化的顺序是怎样的?
  • 原文地址:https://www.cnblogs.com/buguge/p/7728928.html
Copyright © 2011-2022 走看看