理解并自定义HttpModule
前言
继上一篇理解并自定义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="MM" type="MyModule,MMAssembly"/>
3 </HttpModules>
1.type:跟HttpHandler中的一样,有两部分组成,第一部分是完整的类名(含命名空间名),第二部分是所在程序集名(不含.dll)。
2.name:HttpModule的名称,可以跟类名无关。通过HttpApplication对象的Modules属性获取HttpModuleCollection,然后通过name获取对应的HttpModule对象;在Global.asax中通过方法名ModuleName_EventName订阅HttpModule中的事件,这里为MM_具体的事件名,详细请见下面实例。
3.因为对于每个进入工作进程的请求都会经过各已配置的HttpModule的处理(因为HttpModule是订阅应用程序级事件的),所以配置文件中没有path和verb属性(不管是*.aspx还是*.ashx,请求方式为get还是post都会进行处理)。
注意:HttpModule的配置是无需像HttpHandler那样在IIS上进行配置的。
自定义HttpModule
每个HttpModule都继承System.Web.IHttpModule接口,并实现接口的Init(HttpApplication context)和Dispose()方法。如下:
1 public class MyModule:IHttpModule
2 {
3
4 public void Init(HttpApplication context)
5 {
6 context.BeginRequest += 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():这个方法接受一个HttpApplication对象,HttpApplication代表了当前的应用程序,我们需要在这个方法内订阅 HttpApplication对象暴露给客户端的事件。可见,这个方法仅仅是用来对事件进行订阅,而实际的事件处理程序,需要我们另外写方法。
Dispose():在垃圾回收前释放资源。
整个过程很好理解:
- 当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。
- 在创建Module实例的时候会调用Module的Init()方法。
- 在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。
- HttpApplication在其应用程序周期中触发各类事件。
- 触发事件的时候调用Module在其Init()方法中注册过的方法。
关于委托可参考:委托与事件
Global.asax文件与 HttpModule
在asp.net中,Glabal不仅可以注册应用程序和Session事件,还可以注册Http Module暴露出的事件;不仅可以注册系统Module的事件,也可以注册我们自己义的Module暴露出的事件。在具体介绍之前,这里需要首先注意两点:
- 在每处理一个Http请求时,应用程序事件都会触发一遍,但是Application_Start和 Application_End 例外,它仅在第一个资源文件被访问时被触发。
- Http Module无法注册和响应Session事件,对于Session_Start 和 Session_End,只能通过Glabal.asax来处理。
继续上面的例子:
MyModule.cs文件
1 public class MyModule:IHttpModule
2 {
3 public event EventHandler ExposedEvent;//HttpModule事件,供Global.asax来订阅
4
5 public void Init(HttpApplication context)
6 {
7 context.BeginRequest += 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 != 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事件。具体实现机制有待研究!
- BZOJ3667: Rabin-Miller算法
- Numpy 修炼之道 (2)—— N维数组 ndarray
- python爬虫入门(五)Selenium模拟用户操作
- python爬虫入门(六) Scrapy框架之原理介绍
- lambda表达式杂谈
- python爬虫入门(七)Scrapy框架之Spider类
- python爬虫入门(八)Scrapy框架之CrawlSpider类
- python爬虫入门(九)Scrapy框架之数据库保存
- Numpy 修炼之道(1) —— 什么是 Numpy
- TensorFlow修炼之道(3)——计算图和会话(Graph&Session)
- 1.python简介
- 《Python自然语言处理》答案第三章
- 2.python数据类型
- Miller Rabin算法详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Centos7.x+Docker部署RabbitMQ
- LeetCode(1)-找出数组中重复的数字
- LeetCode(面试题:二维数组中的查找)
- 面试题05-替换空格(LeeCode)
- 解决Mybatis当实体类中的属性名和表中的字段名不一致的问题
- 图书管理系统(一)项目框架结构搭建
- Mybatis中模糊查询like语句的使用方法
- win10暴力查看wifi密码
- 再也不怕面试官问java中的goto关键字了?
- 死磕Java之分析short类型
- 死磕Java之Java数据类型的来龙去脉
- 请不要再使用判断进行参数校验了
- 检测假新闻:比较不同的分类方法的准确率
- SpringBoot下载xlsx模板,导出excel数据
- 如何利用机器学习和Gatsby.js创建假新闻网站