从请求管道深入剖析HttpModule的实现机制图文介绍

想要了解底层的原理必须对请求处理过程和页面的生命周期有点了解才方便您入门学习一下内容:
关于请求处理过程和页面的生命周期将会在接下来的日子为大家做一个深入的讲解。
HttpModule的实现机制如下
1.请求到达ISAPIRuntime 的时候通过ProcessReqeust(下文统称pr ) 方法创建 HttpWrokRequest 对象。
2.在执行ISAPIRuntime 的pr 方法时候,方法内部的HttpRuntime 的pr 方法根据HttpWorkRequest 对象创建了上下文对象 HttpContext 。
3.在HttpRuntime 的 pr 方法内部又通过 HttpApplicationFactory 创建了一个处理应用程序的 HttpApplication 实例。
注意:HttpApplication的创建是根据Global.asax文件编译后的类型,再通过反射的方法创建的实例,由于创建实例的过程非常消耗时间和资源,这个则使用了对象池技术
4.在创建HttpApplication 实例的过程中,内部会调用InitInternal 方法,在这个方法里面 调用了HttpModule 的初始化方法,实现了事件的注册。
注意:在实现事件的注册的过程中,内部会去配置文件里面找是否有配置HttpModule模块,如果有则通过反射注册,没有则继续往下走,直到方法跳出。这个过程就是微软的插件机制的体现。
5.事件注册完之后,HttpApplication实例则开始调用自己的pr 方法开始执行页面的生命周期了。
总结:HttpModule 模块的事件注册,就是在HttpApplication 实例内部调用InitInternal 方法,这个方法里面 调用了HttpModule 的初始化方法,实现了事件的注册。
下面的代码是帮助你理解这个过程
1、首先定义一个上下文 类 HttpContext


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 上下文
/// </summary>
public class HttpContext
{
}
}

2.定义两个接口分别为: IHttpHandler 、IHttpModule


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,这个接口主要是在application调用pr方法的时候
/// 实现调用具体页面或一般处理程序的pr方法的。
/// </summary>
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
}
}

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 接口,这个接口主要模拟在Application 的 InitInternal方法内部实现事件的注册
/// </summary>
public interface IHttpModule
{
void Init(HttpApplication application);
}
}

3、定义一个页面类 Page


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 页面类
/// </summary>
public class Page:IHttpHandler
{
/// <summary>
/// 实现了IHttpHandler接口
/// </summary>
/// <param name="context">上下文</param>
public void ProcessRequest(HttpContext context)
{
Console.WriteLine("页面的生命周期....");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("..................");
Console.WriteLine("页面的生命周期结束...");
}
}
}

4.定义一个应用程序类 Application


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
public class HttpApplication:IHttpHandler
{
//初始化方法
public void InitInternal()
{
//从配置文件中读取所有的注册了HttpModule的程序集,然后通过反射出实例,并调用Init方法!!! 下面的MyHttpModule假设是通过反射出来的
IHttpModule httpModule = new MyHttpModule();
httpModule.Init(this);
BindEvent();
}
//Application 自己的事件响应方法
private void BindEvent()
{
BeginRequest += new EventHandler(HttpApplication_BeginRequest);
PostResolveRequestCache += new EventHandler(HttpApplication_PostResolveRequestCache);
EndRequest += new EventHandler(HttpApplication_EndRequest);
}
void HttpApplication_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件响应方法执行了--EndRequest");
}
void HttpApplication_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件响应方法执行了--PostResolveRequest");
}
void HttpApplication_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("application自己的事件响应方法执行了--BeginRequest");
}

//把此方法看成是 http 请求处理的管道
public void ProcessRequest(HttpContext context)
{
//19个事件,23个步骤
Console.WriteLine("开始请求");
//触发第一个事件
BeginRequest(this, null);
//触发第七个事件
PostResolveRequestCache(this, null);
Console.WriteLine("已经获取缓存");
//第七个和第八个事件之间,创建页面对象或一般处理程序
IHttpHandler httpHandler = new Page();
Console.WriteLine("创建页面对象");
//在11 和 12 个事件之间执行pr方法
Console.WriteLine("开始执行页面的生命周期");
httpHandler.ProcessRequest(context);
//最后一个事件
EndRequest(this, null);
Console.WriteLine("结束请求");
}
public event EventHandler BeginRequest;
public event EventHandler PostResolveRequestCache;
public event EventHandler EndRequest;
}
}

5.模拟请求管道中的执行过程


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
class Program
{
static void Main(string[] args)
{
//ISAPIRuntime
//假设根据请求创建了HttpContext上下文
HttpContext context = new HttpContext();
//假设从HttpApplicationFactory创建出来
HttpApplication application = new HttpApplication();
//把所有注册在配置文件中的HttpModule加载并执行其Init方法
application.InitInternal();
//调用pr方法开始执行页面的pr方法
application.ProcessRequest(context);
Console.ReadKey();
}
}
}

6.自定义一个HttpModule


代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HttpApplicationProcessMethodDemo
{
/// <summary>
/// 自定义的HttpModule模块
/// </summary>
public class MyHttpModule : IHttpModule
{
/// <summary>
/// 实现了IHttpModule接口
/// </summary>
/// <param name="application"></param>
public void Init(HttpApplication application)
{
//注册事件
application.BeginRequest += new EventHandler(application_BeginRequest);
application.PostResolveRequestCache += new EventHandler(application_PostResolveRequestCache);
application.EndRequest += new EventHandler(application_EndRequest);
}
void application_EndRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注册了EndRequest方法");
}
void application_PostResolveRequestCache(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注册了PostResolveRequestCache方法");
}
void application_BeginRequest(object sender, EventArgs e)
{
Console.WriteLine("HttpModule注册了BeginRequest方法");
}
}
}

通过以上的步骤就实现了整个管道的执行过程和HttpModule的实现原理了。
下面是效果图

(0)

相关推荐

  • asp.net通过HttpModule自动在Url地址上添加参数

    然而手机客户端又不支持Session和Cookie传值,其他方法给页面赋值再传值显得太麻烦了,而且还不易维护,容易弄丢出错,于是想到了用HttpModule来把cid参数赋在Url地址上,让url把cid参数每页自动传递下去,需要用cid时只要通过Requet["cid"]获取,这样就不用为传值而烦恼了. 以下是配置方法和源码. 1)在web.config配置文件中添加以下节点 复制代码 代码如下: <httpModules> <add name="Http

  • asp.net 通过httpModule计算页面的执行时间

    创建一个类库,建立如下类: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Web;//引用web命名空间 using System.Text; namespace TimerHttpModule { public class Class1:IHttpModule//继承IHttpModules { public void Init(HttpApplication application)//实现IH

  • Asp.net使用HttpModule压缩并删除空白Html请求的实现代码

    同时我们还可以删除一些空白 段,空行,注释等以使得HTML文档的尺寸变得更小. 让我们先来实现压缩与删除空白类, 继承自Stream类: 复制代码 代码如下: /// <summary> /// CompressWhitespaceFilter /// </summary> public class CompressWhitespaceFilter : Stream { private GZipStream _contentGZipStream; private DeflateSt

  • HttpHandler HttpModule入门篇

    生命周期中涉及到几个非常重要的对象:HttpHandler,HttpModule,IHttpHandlerFactory,他们的执行(顺序)大致的执行过程是这样的:client端发送页面请求,被IIS的某个进程截获,它根据申请的页 面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll; .aspx->ISAPI.dll).而页面处理程序在处理过程中,则要经历HttpModule,HttpHandler的处理:前者HttpModule用于页面处理前和处理后的一些事件的处理

  • 从请求管道深入剖析HttpModule的实现机制图文介绍

    想要了解底层的原理必须对请求处理过程和页面的生命周期有点了解才方便您入门学习一下内容: 关于请求处理过程和页面的生命周期将会在接下来的日子为大家做一个深入的讲解. HttpModule的实现机制如下: 1.请求到达ISAPIRuntime 的时候通过ProcessReqeust(下文统称pr ) 方法创建 HttpWrokRequest 对象. 2.在执行ISAPIRuntime 的pr 方法时候,方法内部的HttpRuntime 的pr 方法根据HttpWorkRequest 对象创建了上下文

  • 关于HttpHandler与HttpModule的理解和应用方法

    神秘的HttpHandler与HttpModule        大学时候我是从拖控件开始学习asp.net的,对.net的很多类库对象都不是很了解.所以看到大家写一些个性的asp.net名词,就感觉asp.net总有一层神秘的面纱笼罩着,让我琢磨不透,相信园子里面也有很多和我经历差不多的.net攻城师.在以前看HttpHandler与HttpModule都是神秘莫测的.哈哈,今天我为大家展示下我对他的理解,以及应用. 也许你不懂HttpHandler与HttpModule(大侠Return),

  • ASP.Net 请求响应流程简述

    一.浏览器请求页面的简单流程 当浏览器请求静态页面时,会发送请求给服务器软件,服务器软件直接去找对应的静态页面,并返回给浏览器. 当浏览器请求动态页面时,服务器软件收到请求,发现处理不了.aspx文件,就去映射表当中根据后缀名找对应的处理程序(aspnet_isapi.dll),这个处理程序实现了服务器软件提供的接口,即服务器软件通过接口调用了这个处理程序当中的方法.aspnet_isapi.dll会将请求转交给.Net Framework,由它处理动态页面,创建页面对象,生成相应报文,响应给浏

  • Linux通过匿名管道进行进程间通信

    本文研究的主要是Linux通过匿名管道进行进程间通信的相关内容,具体介绍如下. 在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式--匿名管道,通过它进程间可以交换更多有用的数据. 一.什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号"|"来使用管道,但是管理的真正定义是什么呢?管道是一个进程连接数据流到另一个进程的通道,它通常是用作把一个

  • .Net Core下HTTP请求IHttpClientFactory示例详解

    使用方式 IHttpClientFactory有四种模式: 基本用法 命名客户端 类型化客户端 生成的客户端 基本用法 在 Startup.ConfigureServices 方法中,通过在 IServiceCollection 上调用 AddHttpClient 扩展方法可以注册 IHttpClientFactory services.AddHttpClient(); 注册之后可以像依赖注入DI似得在类中通过构造函数注入形式使用,伪代码: class A { private readonly

  • 使用NLog给Asp.Net Core做请求监控的方法

    为了减少由于单个请求挂掉而拖垮整站的情况发生,给所有请求做统计是一个不错的解决方法,通过观察哪些请求的耗时比较长,我们就可以找到对应的接口.代码.数据表,做有针对性的优化可以提高效率.在 asp.net web api 中我们可以通过注册一个 DelegatingHandler 来实现该功能.那在 asp.net core 中该如何实现呢? 一:比较 asp.net web api 和 asp.net core 的请求管道 观察这两张图,可以发现他们非常的相似,都是管道式的设计,在 asp.ne

  • ASP.NET Core扩展库之Http请求模拟功能的使用

    如今,完全独立的业务应用几乎不存在,不管是在企业内部微服务之间的调用,还是与外部第三方服务的调用,Http的API交互是常见的场景,这些实际情况给我们的开发带来了比较大的挑战,一是第三方服务可能会牵制我们的开发进度,特别是在多团队开发的情况下,由于依赖于其他团队的服务,有时候需要等待其他团队的进度,导致自己团队的无效等待.有时因为其他团队的延期,导致团队的被动延期.二是第三方服务的质量问题或开发过程中的频繁更新导致的部署问题,将严重拖累自己团队的开发进度,同时让你无法专心的开发自己的服务.三是单

  • ASP.NET Core的中间件与管道介绍

    今天来讨论一个ASP.NET Core 很重要概念管道和中间件,在ASP.NET Core中,针对HTTP请求采用pipeline也就是通常说的管道方式来处理,而管道容器内可以挂载很多中间件(处理逻辑)“串联”来处理HTTP请求,每一个中间件都有权决定是否需要执行下一个中间件,或者直接做出响应.这样的机制使得HTTP请求能够很好的被层层处理和控制,并且层次清晰处理起来甚是方便. 示意图如下: 为了再次说明管道和中间件的概念,举一个官方给出的权限验证的例子,中间件A,B分别按顺序挂载在管道容器中,

  • ASP.NET Core基础之请求处理管道

    了解ASP.NET处理管道 为了理解ASP.NET Core中的请求处理管道概念,让我们修改Startup类的Configure()方法,如下所示. 在这里,我们将三个中间件组件注册到请求处理管道中. 如您所见,前两个组件是使用Use() 扩展方法注册的,因此它们有机会在请求处理管道中调用下一个中间件组件. 最后一个使用Run() 扩展方法注册,因为它将成为我们的终止组件,即它将不会调用下一个组件. 了解ASP.NET Core请求处理管道执行顺序 为了理解这一点,让我们将上面的输出与下图进行比

  • 学习SpringMVC——如何获取请求参数详解

    @RequestParam,你一定见过:@PathVariable,你肯定也知道:@QueryParam,你怎么会不晓得?!还有你熟悉的他(@CookieValue)!她(@ModelAndView)!它(@ModelAttribute)!没错,仅注解这块,spring mvc就为你打开了五彩斑斓的世界.来来来,不要兴(mi)奋(hu),坐下来,我们好好聊聊这么些个注解兄弟们~~~(wait, 都没有听过? 好,来,你坐前排,就你!)  一.spring mvc如何匹配请求路径--"请求路径哪家

随机推荐