超凡双生txt丫丫网:ASP.NET页面处理(一) - Daniel@blog - CSDN博客

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 23:15:52
  ASP.NET 页面处理 (一)
 一, Web服务器
       在windows平台中, ASP.NET由IIS提供支持, IIS由一个叫 inetinfo.exe 的可执行文件表示, 它是一个非托管Win32程序, 且并不是一个CLR窑主. IIS通过提供的ISAPI扩展技术使得开发者可以开发称为ISAPI扩展和ISAPI筛选器的组件来扩充Web服务器的功能, 即处理对自定义资源的请求. 它们是一些win32 DLL, 通过在Web服务器的配置, 可以将特定资源和你的ISAPI DLL联系起来. 事实上除了少数的资源如htm文件或图片文件之外,大多数资源都由IIS交给了相应的ISAPI DLL来处理. 二,  ASP.NET进程模型
       完全由ISAPI扩展来处理的Web应用程序都是和Web服务器在同一个进程中工作的, 这样实现了性能的最优化,然而从可靠性的角度分析, web服务器和应用程序应该是分离的, 它们应该工作在不同的进程中, 但这样一来使得性能受到影响. ASP.NET同时考虑了性能和可靠性, 它使用分离的进程模型, 包含了两个元素:  一个在进程内作为一个连接器, 控制器, 另一个作为进程外的辅助进程,  或说工作者进程. 这提供了一个灵活的机制, 使得应用程序和工作者进程分离, 即提供服务的工作者进程可随时中止, 却不会影响应用程序的寿命.三, ASP.NET运行时构成
       ASP.NET的ISAPI DLL是 aspnet_isapi.dll , 在web服务器中, 所有的ASP.NET资源都指向这个文件, 它是一个非托管程序, 也不是CLR宿主, 它和IIS工作在同一进程中, 负责接收请求并对其进行分派, 并且它会创建工作者进程, 对于ASP.NET来说, 这个辅助进程是 aspnet_wp.exe, 除此之外 aspnet_isapi.dll 还负责监控工作者进程的执行情况, 可以在性能降低的时候终止它.
       工作者进程寄宿了CLR, 它用IIS中的虚拟目录来区分应用程序, 并为每一个对新应用程序的请求创建一个AppDomain, 每一个新应用程序请求都将导致产生一个新的AppDomain, 这些AppDomain都在同一个工作者进程中, 而对一个正在运行的应用程序的请求仅会被创建一个新的应用程序实例. 出于性能考虑, aspnet_isapi.dll 使用异步方式将请求转发给工作者进程, 而工作者进程必须保持请求被处理的顺序, 并且只有在ISAPI中的内部请求表中改变了当前请求的状态后, 该请求才被工作者进程处理, 所以, 反方向的通讯是同步进行的.
       除了aspnet_isapi.dll 和 aspnet_wp.exe 这两个重要的组成部分以外, ASP.NET还有其它一些组件: * aspnet_filter.dll 它是一个 ISAPI filter 用来备份ASP.NET的无Cookie会话状态.
 * aspnet_state.exe 是一个windows服务, 可以在本地或远程运行, 它用来在web应用程序的内存空间之外保存 会话信息, 该服务启动后, 可在应用程序的配置文件中设置, 使所有会话信息保存在此进程的内存中.四, ASP.NET基本处理过程
       当请求到达IIS时, 它会判断资源类型, 如果是ASP.NET资源, 则ASP.NET ISAPI启动工作者进程, 并将请求排队, 然后分配给工作者进程, 接着辅助进程会回复ISAPI它将处理该请求, 则该请求在 aspnet_isapi.dll 内部状态表中标记为"executing", 辅助进程开始处理, 执行中途辅助进程可能会需要服务器变量并与ISAPI通信. 完成处理后, 响应被发送回 aspnet_isapi.dll,  则该请求的状态被改为"Done", 接着被从请求表中删除.  ASP.NET 页面处理 (二)
 
五, 辅助进程中的请求处理
       所有的对ASP.NET资源的请求实际上是通过ASP.NET HTTP管道来处理的, 辅助进程的一个重要工作就是将请求交给HTTP管道, 那么所谓有HTTP管道是指一系列的托管对象, 它们依次对请求进行处理, 处理完毕后, 应答将会从原路返回. 这些对象由多个称为 HttpModules 的对象和一个最终处理请求的 HttpHandler 对象组成, 请求先经过所有的 HttpModules, 最终到达 HttpHandler, 处理完成后, 应答再次经过这些 HttpModules回到客户端.六, HttpHandlers 和 HttpModules
 HttpHandlers 实际就是实现了 IHttpHandler 接口的类, 我们可以通过实现这个接口来处理自定义的资源,在系统的 machine.config 文件中, 可以在 小节找到特定扩展名的资源相对应的处理类之间的对应关系, 当然我们可以在web.config中改写这个映射.  在我们的类中, 通过改写ProcessRequest方法来自定
义请求处理. HttpModules 实际上就是实现了 IHttpModules 接口的类, 实现该接口的类通过注册特定的HttpApplication类中的事件来将自己插入到Http管道中, 在请求被处理之前及处理完成后都会引发特定的事件, 导致注册了这些事件的HttpModules的方法被调用. 一个实现了 IHttpModules 接口的类可在重写的 Init 方法中注册事件. 同样HttpModules也必须在machine.config 或 web.config 中注册, 在 小节中我们可以找到系统预定义的一些 HttpModules. 七, 进入HTTP管道 (pipeline)
       HttpRuntime是HTTP管道的入口, 每当请求一个新的应用程序, 就会有一个HttpRuntime的对象生成, 也就是说, 每一个AppDomain都有一个自己的HttpRuntime对象. 对象产生以后, 将调用它的 ProcessRequest方法. HttpRuntime的对象会初始化一系列有关请求处理的对象, 如 HttpContext 等. 然后会向 HttpApplicationFactory
请求一个 HttpApplication 对象. 应用程序类是定义了所有应用程序通用的方法和属性, 事件. 它是在 Global.asax 文件背后的类, 这个文件包含对HttpApplication类事件的响应代码, 如果你使用代码后置, 那么在编译时会将动态生成一个叫Global的继承自HttpApplication的类, 并且这个类和你的代码后置类放在同一个程序集中.应用程序工厂类维护了一个 HttpApplication 的对象池, 接收到请求后, 它根据URL来获得虚拟目录的信息, 并用它来和已有的HttpApplication匹配, 它尝试获取应用程序文件 Global.asax 并编译这个类, 然后在生成 HttpApplcation实例时触发 Application_OnStart 事件. 如果实例池中没有可用的对象, 将会创建一个新的实例. HttpApplication 对象会让所有注册过的 HttpModules 对请求进行预处理, 然后再去查找 HttpHandler.八, 页面处理类
 HttpApplication 对象的一个任务就是找到针对特定请求资源的 HttpHandler, 它通过在 machine.config 或web.config 配置文件中根据扩展名找到对应的类, 如对于 .aspx 文件, 是由 PageHandlerFactory类来处理, 事实上, 在ASP.NET中大量使用了厂设计模式, 使我们通过间接的方式来获得同一继承体系的相关对象. PageHandlerFactory调用 GetHandler 方法来返回合适的对象. 在此之前, 它会尝试找到代表廖页面的程序集, 如果没找到, 则编译它, 然后再返回相应的 HttpHandler 对象. 如果我们没有代码后置, 那么这个页面动态编译时会直接继承自 Page, Page类将成为页面处理程序的基类, 如果使用了代码后置, 则在编译时将静态编译这个后置的代码为一个程序集, 注意这个代码后置类也是继承自 Page 的, 动态生成页面的程序集的时候, 这个页面类将继承自代码后置类, 那么页面处理程序的基类将变成代码后置类而不是 Page.  有一点注意的是 Page 类实现了 iHttpHandler 接口. 除此之外, 在web.config中的部分用PageBaseType可以指定页面处理程序的基类. ASP.NET页面处理(三)九, 页面初始化
       找到了最后的 HttpHandler 以后, 这个处理类会执行它的 ProcessRequest 方法对页面进行处理, 这个方法是由 Page 类提供的. 它首先调用 rameworkInitialize 方法来初始化控件树, 这个方法是由 TemplateControl 类提供, 它是 Page 类的基类, 这个受保护的虚函数被所有动态生成的页面类重写, 页面类调用自己的 __BuildControlTree方法初始化所有的控件. 接下来页面会经历它生命周期的几个阶段, 中间还会触发一些事件.十, 自动处理的事件
       为了兼容早期的VB的风格, 在ASP.NET中支持隐式事件绑定, 即不需要显式注册事件, 也可以使事件处理方法得到回调, 条件是必须使用特定的方法名来匹配, 这些方法是:* Page_Init
* Page_Load
* Page_DataBind
* Page_PreRender
* Page_Unload那么对这些方法堍的识别由一个属性来控制, 这个属性是Page指令的 AutoEventWireup, 如果为 false, 则需要显式注册事件, 默认是 true.十一, 页面生命周期
       页面生命周期的第一个阶段是初始化, 在 FrameworkInitialize 方法结束后, 会触发 Init 事件, 顺便提一下, 如果启用了页面跟踪, 即Page指令的 Trace 属性为 true 的话, 在 ProcessRequest 中还会打出相应的信息.        初始化完成后, 将会调用 LoadPageViewState, 这个方法加载页面视图状态, 实际上, 它会递归地调用所有控件的 LoadViewState 方法使得每个控件会得到自己的视图状态, 这个数据是从页面的 __ViewState隐藏字段提交上来的, 有一点要注意的是, 只有 IsPostBack 为 true 的时候, 才会调用这个方法, 而页面第一次被请求的时候是没有这一步的. 每个控件从视图状态中取回属于自己的信息, 并将自己恢复为上次调用时的状态,
       接下来, 控件会用新的提交数据来进行更新, 紧接着, 页面触发 load 事件,  有一些控件会要求在关键值被用户更改后做出反应, 进行相应的处理, 那么它们会对检查自己的属性是否被更改, 并触发相应的事件. 这些控件实现了 IPostBackDataHandler 接口, 这个接口有一个 LoadPostData 方法, 实现了此接口的控件可在这个方法中验证更改, 并引发事件. 这些控件有 CheckBox, ListBox 等, 当发现更改时, 比如 TextBox, 会调用这个接口的另一个方法 RaisePostDataChangedEvent, 对于 TextBox 来说, 引发 TextChanged 事件. 这个是在 load 事件之后进行的.
       如果控件希望处理回发事件, 它必须实现 IPostBackEventHandler 接口, 如 Button, Calendar 等, 如果回发控件中包含这些控件, 页面会调用 RaisePostBackEvent 方法, 对于Button来说, 会找相应的 Click 事件并处理.
       接下来, 页面会触发 PreRender 事件, 在保存视图状态及显示之前, 可以通过这个事件来做一些处理. 这一步完成之后, 将会调用 SavePageViewState 保存视图状态, 它会使 Control 类递归地收集每个控件的键值对, 并保存起来.
       现在页面已经准备好可以显示了, 页面调用 RenderControl 方法,  它个方法产生一个 HtmlWriter 对象, 并将其传给自己的 Render 方法,  它包括对所有成员控件的递归 Render 方法的调用, 并积累所有 Html.  在此之后, 页面将引发 Unload 事件, 可以在此事件中释放一些资源,  最后, 应答会再次通过 HttpModules
并回到客户端.  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/danielhf/archive/2004/07/15/42412.aspx