前言
继上一篇理解并自定义HttpHandler后,有进行了HttpModule的进一步学习,本篇作为一个小结。
主要参考:Asp.Net 构架(HttpModule 介绍) - Part.3
目录
1.到底什么是HttpModule?
2.系统内部的HttpModule。
3.配置HttpModule。
4.自定义HttpModule。
5.Global.asax文件与HttpModule。
到底什么是HttpModule
Asp.net的事件分为三级:应用程序级、页面级和控件级。而HttpModule是通过在管道模型中对Asp.net的应用程序级事件进行订阅,当应用程序级事件触发时调用HttpModule中对应的处理方法。也就是说HttpModule是订阅Asp.net应用程序级事件的入口,依附于HttpApplication对象生命周期的各个事件。
系统内部的HttpModule
Asp.net内部很多功能都以HttpModule形式来实行,如Windows、Forms和PassPort认证、Session机制等。下面是部分的内部HttpModule及其作用。
名称 | 类型 | 功能 |
OutputCache | System.Web.Caching.OutputCacheModule | 页面级输出缓存 |
Session | System.Web.SessionState.SessionStateModule | Session状态管理 |
WindowsAuthentication | System.Web.Security.WindowsAuthenticationModule | 用集成Windows身份验证进行客户端验证 |
FormsAuthentication | System.Web.Security.FormsAuthenticationModule | 用基于COOKIE的窗体身份验证进行客户端身份验证 |
PassportAuthentication | System.Web.Security.PassportAuthenticationModule | 用MS护照进行客户身份验证 |
RoleManager | System.Web.Security.RoleManagerModule | 管理当前用户角色 |
UrlAuthorization | System.Web.Security.UrlAuthorizationModule | 判断用户是否被授权访问某一URL |
FileAuthorization | System.Web.Security.FileAuthorizationModule | 判断用户是否被授权访问某一资源 |
AnonymousIdentification | System.Web.Security.AnonymousIdentificationModule | 管理Asp.Net应用程序中的匿名访问 |
Profile | System.Web.Profile.ProfileModule | 管理用户档案文件的创立 及相关事件 |
ErrorHandlerModule | System.Web.Mobile.ErrorHandlerModule | 捕捉异常,格式化错误提示字符,传递给客户端程序 |
配置HttpModule
自定义HttpModule跟自定义HttpHandler相似,都要在web.config文件中进行配置。形式如下:
1 <HttpModules>
2 <add name&#61;"MM" type&#61;"MyModule,MMAssembly"/>
3 HttpModules>
1.type&#xff1a;跟HttpHandler中的一样&#xff0c;有两部分组成&#xff0c;第一部分是完整的类名&#xff08;含命名空间名&#xff09;&#xff0c;第二部分是所在程序集名&#xff08;不含.dll&#xff09;。
2.name&#xff1a;HttpModule的名称&#xff0c;可以跟类名无关。通过HttpApplication对象的Modules属性获取HttpModuleCollection&#xff0c;然后通过name获取对应的HttpModule对象&#xff1b;在Global.asax中通过方法名ModuleName_EventName订阅HttpModule中的事件&#xff0c;这里为MM_具体的事件名&#xff0c;详细请见下面实例。
3.因为对于每个进入工作进程的请求都会经过各已配置的HttpModule的处理&#xff08;因为HttpModule是订阅应用程序级事件的&#xff09;&#xff0c;所以配置文件中没有path和verb属性&#xff08;不管是*.aspx还是*.ashx&#xff0c;请求方式为get还是post都会进行处理&#xff09;。
注意&#xff1a;HttpModule的配置是无需像HttpHandler那样在IIS上进行配置的。
自定义HttpModule
每个HttpModule都继承System.Web.IHttpModule接口&#xff0c;并实现接口的Init(HttpApplication context)和Dispose()方法。如下&#xff1a;
1 public class MyModule:IHttpModule
2 {
3
4 public void Init(HttpApplication context)
5 {
6 context.BeginRequest &#43;&#61; new EventHandler(context_BeginRequest);
7 }
8
9 void context_BeginRequest(object sender, EventArgs e)
10 {
11 HttpContext.Current.Response.Write("BeginRequest");
12 }
13
14 public void Dispose()
15 {
16 }
17 }
Init()&#xff1a;这个方法接受一个HttpApplication对象&#xff0c;HttpApplication代表了当前的应用程序&#xff0c;我们需要在这个方法内订阅 HttpApplication对象暴露给客户端的事件。可见&#xff0c;这个方法仅仅是用来对事件进行订阅&#xff0c;而实际的事件处理程序&#xff0c;需要我们另外写方法。
Dispose()&#xff1a;在垃圾回收前释放资源。
整个过程很好理解&#xff1a;
- 当站点第一个资源被访问的时候&#xff0c;Asp.Net会创建HttpApplication类的实例&#xff0c;它代表着站点应用程序&#xff0c;同时会创建所有在Web.Config中注册过的Module实例。
- 在创建Module实例的时候会调用Module的Init()方法。
- 在Init()方法内&#xff0c;对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册&#xff0c;实际的方法需要另写)。
- HttpApplication在其应用程序周期中触发各类事件。
- 触发事件的时候调用Module在其Init()方法中注册过的方法。
关于委托可参考&#xff1a;委托与事件
Global.asax文件与 HttpModule
在asp.net中&#xff0c;Glabal不仅可以注册应用程序和Session事件&#xff0c;还可以注册Http Module暴露出的事件&#xff1b;不仅可以注册系统Module的事件&#xff0c;也可以注册我们自己义的Module暴露出的事件。在具体介绍之前&#xff0c;这里需要首先注意两点&#xff1a;
- 在每处理一个Http请求时&#xff0c;应用程序事件都会触发一遍&#xff0c;但是Application_Start和 Application_End 例外&#xff0c;它仅在第一个资源文件被访问时被触发。
- Http Module无法注册和响应Session事件&#xff0c;对于Session_Start 和 Session_End&#xff0c;只能通过Glabal.asax来处理。
继续上面的例子&#xff1a;
MyModule.cs文件
1 public class MyModule:IHttpModule
2 {
3 public event EventHandler ExposedEvent;//HttpModule事件&#xff0c;供Global.asax来订阅
4
5 public void Init(HttpApplication context)
6 {
7 context.BeginRequest &#43;&#61; new EventHandler(context_BeginRequest);//订阅HttpApplication的事件
8 }
9
10 void context_BeginRequest(object sender, EventArgs e)
11 {
12 HttpContext.Current.Response.Write("BeginRequest");
13 OnExposedEvent(new EventArgs());//触发HttpModule自定义事件
14 }
15
16 protected void OnExposedEvent(EventArgs e)
17 {
18 if (ExposedEvent !&#61; null)
19 {
20 ExposedEvent(this, e);
21 }
22 }
23
24 public void Dispose()
25 {
26 }
27 }
Global.asax文件
1 void MyModule_ExposedEvent(object sender, EventArgs e)
2 {
3 Response.Write("xixi");
4 }
上面的MyModule_ExposedEvent方法就会自动订阅了MyModule中的ExposedEvent事件。具体实现机制有待研究&#xff01;