快速入门系列--MVC--01概述
虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入。其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的DI依赖注入概念和注册表模式(GetService)等内容,ExceptionFilter等过滤器就体现AOP的概念,整个MVC内置了一个IOC容器,基本上所有的框架类的对象都是通过这种方式来创建的。此外,一直觉得很j2ee的spring很棒,其实如果大家很熟悉EHAB(微软企业开发库)的话,就会发现它很想Spring了,当然在一些细节上,还是不如Spring方便。
由于是概述,所以内容涉及知识点会很多,但不会很深入,就让我们来对MVC框架有个基本的认识吧,一些不太有特色的知识点不介绍了哈。
终于完成MVC系列的学习,想想挺有意思的,概述居然是最后一个完成的,其实想想也对,最后的总结往往比开头的概述要来的深刻,本系列从去年9月开始,也是我刚开始学着写技术博文,半年过去了,感觉自己还是有一些进步的,加油,熊二!鉴于这部分学习的很多章节的行文显得不够圆润和准确,就不放在首页了,不过可以通过目录访问。此外,俺也会不断的修订这部分内容,使其的实用价值更大,系列目录如下,谢谢您的阅读。
快速入门系列--MVC--01概述
快速入门系列--MVC--02路由
快速入门系列--MVC--03控制器和IOC应用
快速入门系列--MVC--04模型
快速入门系列--MVC--05行为
快速入门系列--MVC--06视图
快速入门系列--MVC--07与HTML5移动开发的结合
过去ASP.NET开发使用的是WebForm,其利用拖放服务器控件,有用的状态(semi-magical statefulness)来处理后台的复杂事务,大家应该都有被ViewState(将表单体进行base64编码,存储在hidden元素中)折磨的经历。而MVC是基于无状态的Web环境的,每一次请求都会有一个完整的生命周期,具体来讲就是每一个请求都是一个新的Controller对象来负责,其遵循约定优于配置(来自Ruby on rails的概念)、支持可插拔性(框架中类均能自定义扩展)等原则。
- 比较有趣的特性:
新的Razor视图引擎,用于生成HTML代码模板,和它类似的有JSP页面的JSTL, EL, Velocity等,其在IDE中的只能感知真心是很棒,编写代码起来非常的顺畅。
支持IValidatableObject接口便于扩展模型的验证,通过设置html元素的属性为data-xxx来实现验证,非常的具有非侵入式特性,此外很好的于JQuery兼容。
提供的新的MVC模板非常的棒棒哒,包括对多种不同客户端的支持,与JQuery Mobile的结合,以及一个Recipes包(Nuget)用于将现有页面转化为支持移动端的版本的组件。此外还有当前最为流行的单页应用程序的模板。
通过BundleConfig将CSS, JS打包压缩减少请求次数和流量,其所在的App_Start目录包含了大部分的配置逻辑。
整合Json.NET、DotNetOpenAuth(包括一个OAuthWebSecurity的简化封装)等开源库。
- IIS(微软的web服务器)相关概念:
在IIS中,当检测到某个HTTP请求时,如果请求的是静态资源则以http回复的形式返回;如果是动态资源,则通过ISAPI动态连接库处理,它被加载到InetInfo.exe进程中,包括相关的元数据。在IIS为解决应用程序间的相互干扰,通过一个应用程序池的机制,为每一个应用程序池建立一个独立的工作线,提供进程的隔离级别的保护,如下图所示w3wp.exe就是相应的工作线程,需要注意的是,默认情况下w3wp.exe进程在一段时间不用后会休眠,在查看时需要注意唤醒。这部分概念在生产系统中,显得比较重要,一些奇葩的高并发、多线程问题都可能与这部分相关。
IIS6.0的基本架构形式
当HTTP.SYS监听到用户的HTTP请求后,分发到W3SVC,W3SVC解析出请求的URL,并根据从Metadata获取的URL与Web应用之间的映射关系得到目标应用,并进一步得到目标应用运行的AppicationPool或工作线程。如果不存在则创建,在其初始化过程中,相应的ISAPI动态连接库(aspnet_isapi.dll)被加载,之后其负责CLR的加载、AppDomain的创建和应用的初始化。
IIS7.0添加了一个Windows进程激活服务(Windows Process Activation Servcie, WAS),用于根据请求的不同协议类型来激活不同的windows服务(覆盖WCF的4中主要协议)。此外IIS7.0将IIS管道和ASP.NET管道有机的整合在了一起,允许本地代码和托管代码两种方式定义IIS Module,形成一个通用管道,例如可以将Form认证应用到静态文件的请求上等。
- ASP.NET管道
大家原来做过WebForm都应该有印象,不管是面试还是实践中,ASP.NET页面的生命的周期是一个非常常见的问题,其实这就是一个请求在管道中的一部分处理过程。接下来,对整个流程(初次请求,发布时也叫点火)做个简单的介绍。
第1步:当IIS接受到请求后,加载对应处理DLL后,会通过AppDomain创建一个应用程序域,随后一个特殊的运行时IsapiRuntime(System.Web.Hosting)被加载。
第2步:它首先会创建一个用于封装请求的IsapiWorkerRequest对象,之后将该对象传递给HttpRuntime,进入ASP.NET管道,HttpRuntime建立相应的HttpContext。
第3步:接着利用HttpApplicaitonFactory创建或获取新的HttpApplication对象(存在一个HttpApplication对象池),其初始化时会根据配置文件加载并初始化相应的HttpModule对象,该对象包含关于生命周期的大量方法,我们通过实现这些方法来完成很多类似面向切面的很多功能,如验证&授权、缓存、日志和统计信息等。
第4步:最终由HttpHandler对象完成请求处理。
HttpApplication对象是基础,由于其某一时刻只能处理一个请求,因而使用对象池的机制来进行管理,其相关事件列表如下。(为了这辈子再不被问这个,还是写了吧!)
名称 |
描述 |
---|---|
BeginRequest |
开始处理请求 |
AuthenticationRequest,, PostAuthenticationRequest |
安全模块对请求进行身份验证 |
AuthorizeRequest, PostAuthorizeRequest |
安全模块对请求授权 |
ResolveRequestCache, PostResolveRequestCache |
使缓存模块利用缓存内容直接响应 |
PostMapRequestHandler |
对于不同的访问资源,使用不同的HttpHandler进行处理,通关过扩展名选择匹配 |
AcquireRequestState, PostAcquireRequestState |
获取当前请求状态,如SessionState |
PreRequestHandlerExecute, PostRequestHandlerExecute |
请求处理的核心,HttpHandler的执行 |
ReleaseRequestState, PostReleaseRequestState |
使状态管理模块释放当前请求的相应状态 |
UpdateRequestCache, PostUpdateRequestCache |
使缓存模块将请求处理结果的内容保存到缓存(均是使用特性,进行声明式的控制) |
LogRequest, PostLogRequest |
为当前请求纪录日志 |
EndRequest |
请求完成 |
HttpModule负责将请求于请求资源类型相匹配的HttpHandler对象进行映射,其初始化时,会将一些功能注册到HttpApplication相应的事件中。典型的HttpModule包括:实现缓存的OutputCacheModule;在无状态HTTP协议上实现基于会话状态的SessionStateModule;实现Windows、Forms、Passport三种典型身份验证的相关模块;实现基于URI和文件ACL授权的UrlAuthorizationModule和FileAuthorizationModule。此外我们还可以通过配置将自定义的httpModule加入其中,例子为<modules><add name="xx" type="xx">。
最终真正处理请求的HttpHandler对象通过ProcessRequest方法处理请求,其相关配置例子为<httpHandlers><add path="xx.svc" verb="*" type="xxxx" validate="false">。
之前介绍了很多关于MVC的基础,接下来通过一个简单的模拟示例来了解MVC框架的实现(参考蒋大神的示例)。该示例展示了请求的路由,Controller的构建与激活,Action的执行,同时穿插介绍了Model绑定器的实现。由于内容比较多,Project压缩包路径为:MVCBase.zip。
参考资料
[1]蒋金楠. ASP.NET MVC4框架揭秘[M]. 上海:电子工业出版社, 2012.
- 【前沿】见人识面,TensorFlow实现人脸性别/年龄识别
- TensorFlow从0到1 - 1 - Hello, TensorFlow!
- iOS自动布局——Masonry详解
- BZOJ 3450: Tyvj1952 Easy
- [编程经验] TensorFlow实现线性支持向量机SVM
- TensorFlow从0到1 - 2 - TensorFlow核心编程
- BZOJ 4318: OSU!
- 讨厌算法的程序员 5 - 合并算法
- 洛谷 P2679 子串
- [编程经验] CVPR2017论文全集下载代码脚本分享
- 讨厌算法的程序员 6 - 归并排序
- [编程经验] Tensorflow中的共享变量机制小结
- 洛谷 P1313 计算系数
- 一文搞懂浏览器自动化测试框架selenium!
- 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.3安装部署最新版Zabbix3.4的方法(图文)
- Linux系统下移植busybox中mkfs.vfat命令
- Linux服务器配置ip白名单防止远程登录以及端口暴露的问题
- Ubuntu上释放空间的5种简单方法
- Linux下Redis允许远程连接的实现方法
- Linux Socket 编程简介和实现
- Linux (Ubuntu 18.04) 下安装vim编辑器的方法
- 把windows下的字体安装到Linux系统下的方法介绍
- Ubuntu 7.10修改软件源的方法
- Linux 僵尸进程产生原因及解决方法
- Ubuntu17.04配置更换国内源的方法
- Centos7硬盘挂载方法
- linux sort多字段排序实例解析
- Linux中Centos7搭建Hadoop服务步骤
- Centos7实现磁盘限额设置方法