热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MVC运行机制(转)

ASP.NET是一种建立动态Web应用程序的技术。它是.NET框架的一部分,可以使用任何.NET兼容的语言编写ASP.NET应用程序。相对于Java、PHP等

ASP.NET是一种建立动态Web应用程序的技术。它是.NET框架的一部分,可以使用任何.NET兼容的语言编写ASP.NET应用程序。相对于Java、PHP等,ASP.NET具有方便性、灵活性、性能优、生产效率高、安全性高、完整性强及面向对象等特性,是目前主流的网络编程技术之一.它可以让开发者快速高效的创建应用程序而不必关注Http,Html,Javascript等底层的详细信息。随着越来越多的企业将网站升级为APS.NET,web应用程序的复杂性不断增加,即使当初MS推出ASP.NET的时候,如何强调codebehind的优势,但是它在架构上回避不了一个问题:如果全部codebehind的话,.cs势必需要担负起同时处理事务逻辑和视图各方面属性的任务。一个是对逻辑的控制,另一个是对视图(服务器控件)的控制。 当预期超过了一定的阈值可能使的Web Forms不再是一种最佳的选择。由于它牺牲掉一个优秀模型的某些方面,比如可维护性,可读性,可测试性以及对HTMl的可控性,越来越多的人认为ASP.NET Web Forms model不太理想。

ASP.NET MVC是创建APS.NET应用的一种新的平台,和传统的 Web Forms一样运行于ASP.NET run-time environment。MVC专注于用户浏览页面时的行为,并且具有不同的试图引擎来控制生成的标记。在标准的ASP.NET runtime environment之上,MVC创建了自身的shell,该shell一端与ASP.NET run-time objects(例如:request,HttpContext)相连,另一端将它本身对象集暴露给内部的组件,非常有意思的是对象集是被注入到ASP.NET MVC runtime shell中的。因此它具有很高的可测试性。MVC是怎么样处理请求的呢,再这之前,我们先了解下ASP.NET的运行机制。

 

I:The ASP.NET Runtime 机制

从开发者的角度来看,Web Forms和MVC是两种不同的开发框架,但是它们具有很多共同点。特别是它们运行于相同的运行时环境:the standard ASP.NET runtime environment.

通常来讲,运行时环境就是一组托管在Web服务器上的组件,用来处理到达服务器的Request并向客户端返回Response。ASP.NET Web Forms and ASP.NET MVC运行时机制是相同的,这就意味着ASP.NET pages and ASP.NET MVC可以同时存在于一个应用程序中。尽管底层机制是相同的,但是ASP.NET MVC and a Web Forms处理request的步骤却完全不同。MVC在ASP.NET runtime之上有自己的run-time shell并且实现自己的管线来处理它获得的请求。

我们通过创建虚拟目录将资源Host到IIS下,原则上,我们可以通过IIS访问置于虚拟目录下的所有Resource,这部仅仅包含一些静态资源文件,比如图片、纯Html文件、CSS、JS等等,也包含一些需要动态执行的文件,比如aspx,asmx等等,我们还可以将Remoting和WCF Service Host到IIS下。对于这些静态的文件,IIS直接提取对应的文件将其作为Http Response返回给Client,但是对于这些需要进一步处理的动态执行的文件,IIS必须将Request进一步传递给对应的处理程序,待处理程序执行完毕获得最终的Http Response通过IIS返回给Client。对于IIS来说,这些处理程序通过ISAPI Extension来体现。对于基于ASP.NET的Resource,其对应的ISAPI Extension为ASP.NET ISAPI,通过一个aspnet_isapi.dll承载。IIS的Metadata database维护着一个称为ISAPI Extension Mapping的数据表,负责将不同类型的Resource影射到对应的ISAPI Extension.

IIS5.x

在IIS5.x中,web服务和ASP.NET应用是分离开来的。IIS5.x运行在一个inetinfo.exe的进程中,InetInfo.exe是一个Native Executive,并非一个托管的程序。IIS分析Request的目标资源文件的扩展名(这里是aspx),通过ISAPI Extension Mapping获知对应的ISPAI为ASP.NET ISAPI,于是加载aspnet_isapi.dll。到此为止,该Request的处理交由ASP.NET ISAPI处理。ASP.NET ISAPI会创建一个叫做aspnet_wp.exe的Worker Process(如果该进程不存在的话),在aspnet_wp.exe初始化的时候会加载CLR,从而为ASP.NET Application创建一个托管的运行环境,在CLR初始化的使用会加载两个重要的dll:AppManagerAppDomainFactory和ISAPIRuntime。通过AppManagerAppDomainFactory的Create方法为Application创建一个Application Domain;通过ISAPIRuntime的ProcessRequest处理Request,进而将流程拖入到ASP.NET Http Runtime Pipeline的范畴,ASP.NET Http Runtime Pipeline对Http Request的处理是一个相对复杂的过程,相关的介绍会放在本篇文章的下一部份。在这里我们可以把它看成是一个黑盒,它接管Request,最终生成Html。

当IIS5.x运行的进程和asp.net运行的进程相互独立时,它们之间采用了Named Pipe来进行通讯。IIS5.x主要应用在Windows XP或Windows 2000操作系统中。

    • 1. 首先,同一台主机上再同一时间只能运行一个aspnet_wp进程,每个基于虚拟目录的ASP.NET Application对应一个Application Domain,也就是说每个Application都运行在同一个Worker Process中,Application之间的隔离是基于Application Domain的,而不是基于Process的。
    • 2. 其次,ASP.NET  ISAPI不但负责创建aspnet_wp Worker Process,而且负责监控该进程,如果检测到aspnet_wp的Performance降低到某个设定的下限,ASP.NET  ISAPI会负责结束掉该进程。当aspnet_wp结束掉之后,后续的Request会导致ASP.NET ISAPI重新创建新的aspnet_wp Worker Process。
    • 3. 最后,由于IIS和Application运行在他们各自的进程中,他们之间的通信必须采用特定的通信机制。本质上IIS所在的InetInfo进程和Worker Process之间的通信是同一台机器不同进程的通信(local interprocess communications),处于Performance的考虑,他们之间采用基于Named pipe的通信机制。ASP.NET ISAPI和Worker Process之间的通信通过他们之间的一组Pipe实现。同样处于Performance的原因,ASP.NET ISAPI通过异步的方式将Request 传到Worker Process并获得Response,但是Worker Process则是通过同步的方式向ASP.NET ISAPI获得一些基于Server的变量。

IIS6.0

    • IIS6.0引入了应用程序池(Application Pool)的概念。IIS6.0先通过组件http.sys来接收客户端的请求,http.sys接收到一个基于aspx的http request,然后它会根据IIS中的Metabase查看该基于该Request的Application属于哪个Application Pool,如果该Application Pool不存在,则创建之。否则直接将request发到对应Application Pool的Queue中。我上面已经说了,每个Application Pool对应着一个Worker Process:w3wp.exe,毫无疑问他是运行在User Mode下的。在IIS Metabase中维护着Application Pool和worker process的Mapping。WAS(Web Administrative service)根据这样一个mapping,将存在于某个Application Pool Queue的request 传递到对应的worker process(如果没有,就创建这样一个进程)。在worker process初始化的时候,加载ASP.NET ISAPI,ASP.NET ISAPI进而加载CLR。最后的流程就和IIS 5.x一样了:通过AppManagerAppDomainFactory的Create方法为Application创建一个Application Domain;通过ISAPIRuntime的ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime Pipeline。
    • 每个应用程序池对应着一个w3wp.exe的工作进程。在IIS Metabase 中维护着应用程序池和工作进程的对照。WAS(Web Administrative service)根据这样一个对照,将存在于某个应用程序池队列的客户端请求传递到对应的工作进程(如果没有,就创建这样一个进程)。在工作进程初始化的时候,加载ASP.NET ISAPI,ASP.NET ISAPI 进而加载CLR。最后的流程就和IIS 5.x一样了:通过AppManagerAppDomainFactory的Create方法为Application创建一个Application Domain;通过ISAPIRuntime的ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime Pipeline(Pipeline是接下来要关注的重点)。
    • IIS6.0主要应用在Windows 2003 server操作系统中。

IIS7.0

    • IIS7.0完全整合了.NET。ASP.NET从ISAPI Extension的角色进入了IIS的核心。IIS7.0处理请求的流程如下:
    • 当客户端浏览器开始HTTP请求一个WEB服务器的资源时,HTTP.sys 拦截到这个请求。
    • HTTP.sys联系WAS向配置存储中心获取信息。
    • WAS 向配置存储中心请求配置信息。applicationHost.config。
    • WWW 服务接受到配置信息,配置信息指类似应用程序池配置信息,站点配置信息等等。
    • WWW 服务使用配置信息去配置 HTTP.sys 处理策略。
    • WAS为请求的应用程序池启动一个工作进程。
    • 工作进程处理请求,并把回复信息返回给HTTP.sys。
    • 客户端接受到处理结果信息。

 

II:HTTP运行期

HTTP运行期处理客户端应用程序(例如Web浏览器)进入的一个Web请求,通过处理它的应用程序的适当组件路由请求,然后产生响应并发回提出请求的客户端应用程序。

进入的HTTP Web请求最先由IIS Web服务器接收到,它在此请求基于ASP.NET已注册处理的扩展名传送到ASP.NET ISAPI上。

HTTP运行期首先创建一个HttpContext对象的实例,它包含了当前正在处理的请求信息,接着创建在处理逻辑中涉及到的所有其他组件都可以使用的上下文对象。HttpContext实例提供了对请求对象(HttpRequest类的实例)和响应对象(HttpResponse类的实例)的访问。

HttpContext

HttpContext体现当前Request的上下文信息,它的生命周期知道整个Request处理结束或者处理超时。通过HttpContext对象我们可以访问属于当前Request的一系列常用的对象:Server,Session,Cache,Application,Request,Response,Trace,User,Profile等等。此外我们可以认为将一些数据放在Items属性中作为状态管理的一种方式,不过这种状态管理和其他一些常用的方式,比如Session,Cache,Application,COOKIE等,具有根本性的不同之处是其生命周期仅仅维持在当前Request的Context中。

HttpApplication

就像其名称体现的一样,HttpApplication基本上可以看成是真个ASP.NET Application的体现。HttpApplication和置于虚拟根目录的Gloabal.asax对应。通过HttpApplicationFactory.GetApplicationInstance创建一个基于Gloabal.asax的HttpApplication对象。在HttpApplicationFactory.GetApplicationInstance方法返回创建的HttpApplication对象之前,会调用一个名为InitInternal的内部方法,该方法会做一些列的初始化的操作,在这些初始化操作中,最典型的一个初始化方法为InitModules(),该方法的主要的目的就是查看Config中注册的所有HttpModule,并根据配置信息加载相应的Assembly,通过Reflection创建对应的HttpModule,并将这些Module加到HttpApplication 的_moduleCollection Filed中。

HttpApplication本身并包含对Request的任何处理,他的工作方式是通过在不同阶段出发不同Event来调用我们注册的Event Hander。

HttpModule

我们上面提到HttpApplication就是一个ASP.NET Application的体现,HttpApplication本身并不提供对Request的处理功能,而是通过在不同阶段出发不同的Event。我们能做的只能是根据我们具体的需求将我们的功能代码作为Event Handler注册到需要的HttpApplication Event上面。注册这些Event Handler,我们首先想到的肯定就直接在HttpApplication对应的Global.asax中定义我们的EventHandler好了。这是最直接的办法,而且Global.asax提供一个简洁的方式是我们的实现显得简单:不需要向一般注册Event一样将Delegate添加到对应的Event上面,而是直接通过方法名称和对应的Event匹配的方式直接将对应的方法作为相关的Event Handler。比如Application_ AcquireRequestState就是AcquireRequestState Event handler。

但是这种方式在很多情况下却达不到我们的要求,更多地,我们需要的是一种Plug-in的实现方式:我们在外部定义一些Request Processing的功能,需要直接运用到我们的Application之中。通过使用HttpModule封装这些功能模块,并将其注册到我们的Application的发式可以很简单的实现这种功能。更多内容参考:http://www.cnblogs.com/jyan/articles/2563794.html

HttpHandler

如果说HttpModule关注的是所有Inbound Request的处理的话,Handler确实关注基于某种类型的ASP.NET Resource的Request。比如一个.apsx的Web Page通过一个System.Web.UI.Page来处理。HttpHandler和他所处理的Resource通过Config中的system.web/handlers section来定义.需要注意的是,我们不但可以单纯地定义一个实现了System.Web.IHttpHandler的Type,也可以定义一个实现了System.Web.IHttpHandlerFactory 的Type。System.Web.UI.Page是一个典型的Httphandler,相信对此大家已经很熟悉了。在最后还说说另一个典型的HttpHandler:System.Web.HttpForbiddenHandler,从名称我们不难看出,它用于那些禁止访问的Resource,现在应该知道了为了Global.asax不同通过IIS访问了吧.

更多内容参考:http://www.cnblogs.com/jyan/articles/2563801.html

 

III:MVC请求过程

 

 

图中可以初步看出一个HttpRequest是如何被ASP.NET和ASP.NET MVC框架执行的:经过IIS和ASP.NET处理后,Core Routing会首先根据URL匹配物理路径上的文件,如果不能匹配则由核心路由模块执行路由,路由被匹配后,MvcRouteHandler会将这个请求“带入”MVC框架,执行Controller和Action,Action可以直接注入response,或者更平常的是返回一个ActionResult,ActionResultExecutedResult方法将被调用,如果是个ViewResult(继承自ActionResult),则会使用WebFormViewEngine转化一个Html,并注入到response。

下图是Web Forms与MVC中运行时环境,可以看出,MVC运行时环境是原始ASP.NET运行时环境的定制版本。

 

 

[参考]http://www.cnblogs.com/artech/archive/2007/09/13/891266.html

转:https://www.cnblogs.com/syf/archive/2013/03/07/2948271.html



推荐阅读
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • 本文介绍了腾讯最近开源的BERT推理模型TurboTransformers,该模型在推理速度上比PyTorch快1~4倍。TurboTransformers采用了分层设计的思想,通过简化问题和加速开发,实现了快速推理能力。同时,文章还探讨了PyTorch在中间层延迟和深度神经网络中存在的问题,并提出了合并计算的解决方案。 ... [详细]
author-avatar
jason2502893743
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有