HttpModule

来源:互联网 发布:淘宝运营推广钻通 编辑:程序博客网 时间:2024/05/22 03:33

HttpModule工作方式:订阅管线事件,并在事件处理中执行所需要的相关操作.

      它的无限强大处理能力正是来源于它可以订阅管线事件,因此,它有能力在许多阶段修改请求,这些修改的请求可能会影响最终的处理结果(比如完全不通过HttpHandler直接处理请求)

HttpModule加载方式:

      Asp.net会为每一个请求分配一个HttpApplication对象,在每一个HttpApplication对象初 始化的过程中,它会加载所有在Web.Config上注册的HttpModule,由于Asp.net并不是只创建一个HttpApplication对象,而是创建多个HttpApplication对象,因此每个HttpModule的Init()事件可能会被多次调用,许多人喜欢在这做类初始化操作,那么需要注意修改静态成员变量时的线程安全情问题,所以,如果需要执行初始化操作,最好还是在Global的Application_Start事件中处理.

HttpModule性能问题

    对于每个Asp.net请求,每个HttpModule会在它所订阅的事件中,会执行一些操作逻辑,这些操作逻辑对请求可能是无用的,因此会浪废一些资源和白白执行一些无意义的代码.

 以下是微软在我们项目中加载的HttpModule

protected void Page_Load(objectsender,EventArgse)

{   

      HttpApplication app = HttpContext.Current.ApplicationInstance;           

     StringBuilder sb = new StringBuilder();   

     foreach( string module in app.Modules.AllKeys )        

         sb.AppendFormat(module).Append("<br />");   

     Response.Write(sb.ToString());} 总共有14个,因此可以将一些不需要的移除

 HttpModule常见用法

  1 Url重写

      通常情况下,将一个Url:/Product/12 重写为/Product.aspx/?id=12,这样的目的是让地址更友好

      实现原理:订阅管线的PostAuthorizeRequest事件,检查Url是不是期望修改的模式,如果是,调用Context.RewritePath()方法完成URL重写操作.在管线的后续处理过程中,最终会使用新的URL映射到的个HttpHandler上,注意:选择的事件只需要在第10个事件之前就可以,因为在第10个事件之前重写URL,才能保证将请求映射到合理的处理器上执行。(代码详见FishLi)

 2Url路由

   通过HttpModule实现Url路由是MVC中常用的模式

    实现原理:订阅管线中的PostResolveRequestCache事件,检查Url是不是期望的路由模式,如果是,则根据请求中所包含的信息找到一个合适的处理器,并临时保存这个处理器,重写Url到一个Asp.net可以映射的地址,在管线的PostMapRequestHandler事件中,检查前面有没有临时保存处理器,如果有,则重新给Context.Handler赋值,并重写Url原始地址。

public class MyServiceUrlRoutingModule : IHttpModule{    private static readonly object s_dataKey = new object();    public void Init(HttpApplication app)    {        app.PostResolveRequestCache += new EventHandler(app_PostResolveRequestCache);        app.PostMapRequestHandler += new EventHandler(app_PostMapRequestHandler);    }    private void app_PostResolveRequestCache(object sender, EventArgs e)    {        HttpApplication app = (HttpApplication)sender;        // 获取合适的处理器,注意这是与URL重写的根本差别。        // 即:根据当前请求【主动】寻找一个处理器,而不是使用RewritePath让Asp.net替我们去找。        MyServiceHandler handler = GetHandler(app.Context);        if( handler == null )            return;        // 临时保存前面获取到的处理器,这个值将在PostMapRequestHandler事件中再取出来。        app.Context.Items[s_dataKey] = handler;        // 进入正常的MapRequestHandler事件,随便映射到一个处理器就行了。        app.Context.RewritePath("~/MyServiceUrlRoutingModule.axd");    }    private void app_PostMapRequestHandler(object sender, EventArgs e)    {        HttpApplication app = (HttpApplication)sender;        // 取出在PostResolveRequestCache事件中获得的处理器        MyServiceHandler handler = (MyServiceHandler)app.Context.Items[s_dataKey];        if( handler != null ) {            // 还原URL请求地址。注意这里和URL重写的差别。            app.Context.RewritePath(app.Request.RawUrl);            // 还原根据GetHandler(app.Context)调用得到的处理器。            // 因为此时app.Context.Handler是由"~/MyServiceUrlRoutingModule.axd"映射得到的。            app.Context.Handler = handler;        }    }

注意:在MyServiceUrlRoutingModule中,我将请求【路由】到一个MyServiceUrlRoutingModule的实例,而不是让Asp.net根据URL来替我选择

 

     

0 0
原创粉丝点击