mvc源码解读(3)-扩展:asp.net的两大核心组件HttpModule&&HttpHandler

       在前面两篇文章中,我们仅从mvc源码的层次上解析了mvc执行的一些前期准备工作,那么这一篇文章我们将再次深入的探讨一个HTTP请求如何在IIS服务器以及.Net FrameWork环境中被解析并返回给客户端。在处理客户端请求的时候,这里会涉及到两个模块:IIS服务器和.net FrameWork环境。IIS服务器是运行在非托管的环境下,Asp.net管道则是在托管环境下的,两者之间通过ISAPI接口连通在一起。我在前面也讲过mvc其实走的也是asp.net管道,只不过是让UrlRoutingModule 实现了IHttpModule接口,并在Init中注册了PostResolveRequestCache事件,在该事件中进行了相应的扩展使得用于处理HTTP请求的处理器不再是WebForm模式下的页面类的处理器或是一般处理程序,而是MvcHandler处理器。同时后期不再是执行页面生命周期,打造控件树,而是通过视图引擎将处理后的结果返回给用户。

      客户端的请求经过IIS的简单处理之后进入.net FrameWork环境,ISAPIRuntime会接管当前的HTTP请求,ISAPIRuntime首先会创建一个WorkRequest对象用于封装当前的HTTP请求,同时将WorkRequest对象传递给了Asp.net运行时HttpRuntime,到了这里意味着HTTP请求正式的进入到了Asp.net管道,在Asp.net事件管道里面涉及到两个十分重要的组件:HttpModule过滤器和HttpHanlder处理器。我们来一一介绍。

     首先,我们来看HttpModule,其实不论是HttpModule还是HttpHandler都只是一个统称而已,分别代表某一类的过滤器和处理器。所有的HttpModule都必须实现IHttpModule接口,该接口定义如下:

public interface IHttpModule
{
    // Methods
    void Dispose();
    void Init(HttpApplication context);
}

它的强大之处在于它可以订阅任意的管道事件,有能力修改每个阶段的请求,将修改之后的请求交给HttpHandler处理器处理,因此这有可能影响到请求的处理。这主要体现在每一个HttpHandler都要实现了接口里面的Init(),因为web应用程序在启动的时候,会首先在配置文件中读取<modules></modules>节点,获取到相应的HttpModule处理器,并调用HttpModule里面的Init()方法实现订阅事件的目的。废话不多说,我们还是举一个URL重写的例子来讲解HttpModule的用法吧。我们自定义一个Httpmodule---MyUrlModule,让它实现IHttpModule接口,如下面代码所示:

          public class MyUrlModule:IHttpModule    

         { 

                public void Init(HttpApplication context)        

                 {

                        context.BeginRequest += context_BeginRequest;        

                }

        void context_BeginRequest(object sender, EventArgs e)        

         {            

             HttpApplication app = sender as HttpApplication;            

             app.Context.Response.ContentEncoding = System.Text.Encoding.UTF8;            

             app.Context.Response.ContentType = "text/html"; 

            app.Context.Response.Write("原始路径为:" + app.Context.Request.Url.AbsolutePath);

             //将原始路径:NewsPage.aspx/id/4转换为NewsPage.aspx?Id=4--即URL重写的本质://获得原始的路径---请求报文传递过来的URL            

            string sourcePath = app.Context.Request.Url.AbsolutePath+"/id/4"; //将URL进行分割            

            string[] urls = sourcePath.Split('/'); //获得类类名跟后缀名            

            string strClassName = urls[1];            

            string[] strClassAndExtend = strClassName.Split('.'); //获得类名            

            string className = strClassAndExtend[0];//获得后缀名            

            string extend = strClassAndExtend[1]; //获得传递过来的参数            

            string strParas = urls[2];//获得传递过来的参数值            

            string strParasValue = urls[3];//将伪装的静态页转换为动态页面            

            app.Context.RewritePath(className+"."+"aspx"+ "?" + strParas + "=" + strParasValue);        

       }

同时HttpModule在Web.Config中配置文件的设置如下:

    <system.webServer>
      <modules>
        <add name="url" type="URLModule.MyUrlModule"/>
      </modules>
    </system.webServer>

       这样在web程序初始化的时候或是处理请求的时候都会调用HttpModule的Init事件,因此在这里面我们需要特别注意一点:Asp.net中会为每一个到达管道的请求(不包括只是请求.js,.css或者img等资源)都创建一个HttpApplication对象,当HttpApplication对象初始化的时候都会加载Web.Config中注册的HttpModule节点。而Asp.net中创建的HttpApplication对象并不是唯一的,也就是意味着HttpModule中的Init方法可能会被调用多次,因此对于类似初始化的操作这里还是不适合的。还有一点我们也需要注意,我们要为Httpmodule订阅合适的管道事件。我之前在项目开发的时候就遇到过这样的一个问题:利用Seesion(现在想想用session确实不怎么好)对用户的是否登录进行判断,当时也是订阅BeginRequest事件,但是怎么操作都无法显示预期的效果。后来才发现在PostAcquireRequestState与PostRequestHandlerExecute事件中才开始加载了页面类的Session对象,自然就无法在BeginRequest事件中做用户登录的判断了。

       我们再来看看HttpHandler处理器,所有的HttpHandler都是实现了IHttpHandler接口,HttpHandler是处理所有请求的核心对象。绝大多数的的请求都在PostMapRequestHandler事件中被映射到一个HttpHandler对象, 然后在PreRequestHandlerExecute事件中执行处理过程,因此也常把这类对象称为处理程序,像在WebForm模式下的一般处理程序.ashx和Page就是一个处理器。我个人认为一般处理程序.ashx文件就像一个纯正的处理器,在WebForm编程中,我使用一般处理程序的概率还是很高的,简洁高效且在js或是Ajax中可以直接指定要哪一个一般处理器来处理我们的请求。当然了我们依然也可以创建我们自己的Httphandler处理器,将某一类请求交给我们自己定义的Httphandler处理,这样的话我们就得在Web.Config中注册我们处理器。

 <httpHandlers>
    <add path="/MyTestHttpModule.axd" verb="*" validate="false" type="URL.MyTestHttpModule"/>
  </httpHandlers>

 那么在mvc中HttpHandler处理器就是MvcHandler,并由它处理请求实现了mvc。

 对HttpHandler这一块理解的还不是很透彻,写下愚见,望共勉~~~~

 

 

 

 

转载于:https://www.cnblogs.com/ghhlyy/archive/2013/01/29/2880889.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值