ASP.NET MVC学习(6)Asp.Net管道模型

序言

梳理出来每一个涉及到的对象

HttpRuntime

HttpApplication

HttpContext 

HttpRequest

HttpResponse

HttpSessionState

HttpHandler

HttpModule

理解并自定义HttpHandler

理解并自定义HttpModule

HttpHandler和HttpModule的区别

HttpModule的认识

HttpModule是向实现类提供模块初始化和处置事件。当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。

1、asp.net的HTTP请求处理过程

ASPNETHTTP

 

2、HttpModule工作原理

3、编写自己的HttpModule

要实现HttpModule,必须实现接口IHttpModule。下面是IHttpModule接口分析:

using System;

using System.Web;

namespace ClassLibrary1

{

    public class MyHttpModule : IHttpModule

    {

        public void Dispose() { }

        public void Init(HttpApplication context)

        {

            context.BeginRequest += new EventHandler(Application_BeginRequest);

            context.EndRequest += new EventHandler(Application_EndRequest);

        }

        public void Application_BeginRequest(object sender, EventArgs e)

        {

            HttpApplication application = sender as HttpApplication;

            HttpContext context = application.Context;

            HttpResponse response = context.Response;

            response.Write("这是来自自定义HttpModule中有BeginRequest");

        }

        public void Application_EndRequest(object sender, EventArgs e)

        {

            HttpApplication application = sender as HttpApplication;

            HttpContext context = application.Context;

            HttpResponse response = context.Response;

            response.Write("这是来自自定义HttpModule中有EndRequest");

        }

    }

}
View Code

web.config

<httpModules>
      <add name="myHttpModule" type="ClassLibrary1.MyHttpModule,ClassLibrary1"/>
</httpModules>
View Code

Mvc动态注册HttpModule详解

我们知道HttpApplication在初始化的时候会初始化所有配置文件里注册的HttpModules,那么有一个疑问,能否初始化之前动态加载HttpModule,而不是只从Web.config里读取?

答案是肯定的, ASP.NET MVC3发布的时候提供了一个Microsoft.Web.Infrastructure.dll文件,这个文件就是提供了动态注册HttpModule的功能,那么它是如何以注册的呢?我们先去MVC3的源码看看该DLL的源代码。

怎么样,这个功能不错吧,不需要每次都在web.config里定义你的HttpModule咯,而且我们以后封装自己的类库就方便多了,不需要在网站程序集里指定代码去启动自己封装好的单独类库了,因为我们可以在自己的类库里直接使用这种方式实现自动注册的功能。

 

注册Httpmodule可以让我们使用HttpApplication对象中的处理管道事件

目前大家所熟知的应该有2种方式来使用HttpApplication对象中的处理管道事件

第一种是通过Global.asax全局文件

第二种是通过配置文件来注册httpmodule

 

DynamicModuleUtility.RegisterModule方法

通常通过 Web.config 文件的 <modules> 部分注册模块。然而,在运行时可通过 RegisterModule(Type) 方法注册模块。

 不用配置 web.config  的   <httpModules>  or <modules> 节点了!!!

Microsoft.Web.Infrastructure.dll与PreApplicationStartMethodAttribute属性

using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
 
 
[assembly: PreApplicationStartMethod(typeof(xxx.PreApplicationStartRegist), "PreStart")]
namespace xxx
{
    /// <summary>
    /// 动态注册 IHttpModel
    /// </summary>
    public class PreApplicationStartRegist
    {
        private static bool hasLoaded;
        static object _lock = new object();
        public static void PreStart()
        {
            Console.WriteLine("PreApplicationStartRegist.PreStart() 执行...");
            lock (_lock)
            {
                if (!hasLoaded)
                {
                    hasLoaded = true;
                    DynamicModuleUtility.RegisterModule(typeof(xxx.Service.PerformanceMonitorModule));
                    Console.WriteLine("PreApplicationStartRegist.PreStart() 注册 IHttpModle 成功!");
                }
            }
        }
    }
}
 
namespace xxx.Service
{
    /// <summary>
    /// http 管道,用于记录访问日志
    /// </summary>
    public class PerformanceMonitorModule : IHttpModule
    {
}
View Code

代码实现动态注册HttpMoudle

 //通常通过 Web.config 文件的 <modules> 部分注册模块。然而,在运行时可通过 RegisterModule(Type) 方法注册模块。
                DynamicModuleUtility.RegisterModule(typeof(CryptographyHttpModule));

 RegisterModule 基础结构。动态注册 IHttpModule 模块。

 

WebActivatorEx

 

自定义HttpModule

class StartMethodCallingModule : IHttpModule
{
    private static object _lock = new object();
    private static int _initializedModuleCount;

    public void Init(HttpApplication context)
    {
        lock (_lock)
        {
            // Keep track of the number of modules initialized and
            // make sure we only call the post start methods once per app domain
            if (_initializedModuleCount++ == 0)
            {
                RunPostStartMethods();
            }
        }
    }

    public void Dispose()
    {
        lock (_lock)
        {
            // Call the shutdown methods when the last module is disposed
            if (--_initializedModuleCount == 0)
            {
                RunShutdownMethods();
            }
        }
    }
}
View Code

 

WebActivator的实现原理详解

WebActivator提供了3种功能,允许我们分别在HttpApplication初始化之前,之后以及ShutDown的时候分别执行指定的代码,示例如下:

[assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass1), "PreStart")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(A.InitClass1), "PostStart")]
[assembly: WebActivator.ApplicationShutdownMethod(typeof(A.InitClass1), "ShutDown")]

 

//使用PreApplicationStartMethod注解的作用是在mvc应用启动之前执行操作
[assembly: PreApplicationStartMethod(typeof(FastExecutor.Base.Util.PluginUtil), "PreInitialize")]

 

HttpHandler和HttpModule的区别

HttpHandler与HttpModule的理解与应用

ASP.NET Framework处理一个Http Request的流程:

HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()

ASP.NET 请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET 把http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给客户端。我们可以在每个HttpModule中都可以干预请求的处理过程。

注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。
ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后,仍经过Pipeline中各个HttpModule的处理,最后将HTML发送到客户端浏览 器中。
https://www.cnblogs.com/zhouds/archive/2011/07/20/2111346.html
 

MvcHandler是如何接管请求的

 

我们能否自己来写一个自定义的HttpHandler通过Route动态注册进去,来实现我们自己的自定义扩展

https://www.cnblogs.com/TomXu/p/3756863.html

HttpContext

HttpContext.Current.Items用途

首先,我们看HttpContext.Current.Items的用途,它只作用于单独的一个用户请求(HttpContext.Current.Items valid for a single HTTPRequest)。

完成这个请求,服务器信息传回浏览器的时候,这个Item集合将丢失。而Session对象是针对用户的本次会话,也就是作用 于多个用户请求,在Session失效后才丢失其中的信息。

既然HttpContext.Current.Items的生命周期如此之短,那在什么情况下可以加以利用呢。

这里指出,HttpContext.Current.Items可以在HttpModule和HTTPHandler之间共享数据时使用,因为每次用户请求都要通过HTTP 运行时管道HttpModule 、HTTPHandler 。当你实现IHttpMoudle的方法来通过HttpMoudle向用户请求传递信息。

你可以用HttpContext.Current.Items 在不同请求页,不同的HttpModule中传输数据,但是一旦请求结束,数据回发,这个集合中的数据将自己丢失。

HttpContext.Current.Items.Add

资料

理解HttpHandler与HttpModule

Mvc动态注册HttpModule详解

MVC之前的那点事儿系列

Asp.Net构架(Http请求处理流程) - Part.1

Asp.Net 构架(Http Handler 介绍) - Part.2

Asp.Net 构架(HttpModule 介绍) - Part.3

https://www.cnblogs.com/caoyc/p/6409062.html

posted @ 2021-10-17 16:38  ~沐风  阅读(223)  评论(0编辑  收藏  举报