Spring 源码分析(四) ——MVC(二)概述

前    言

        Spring 是一种企业应用开发框架,在实际开发中起到了应用平台的做用,有点像企业应用中的“操做系统”,从而为企业应用资源的使用提供一致的环境。具体来讲,Spring 提供的框架特性有 IoC 容器、AOP、事务处理、ORM 等等。在实际的软件产品开发中,若是有某些特性的使用比较广泛,那么就能够考虑将这些特性做为框架特性来实现,而后经过框架特性进行有效的封装,从而提升应用开发效率。 前端

        而 Spring MVC 是 Spring 的一种重要模块,做为开源的 Java EE 应用框架,不少 Web 应用是由 Spring 来支撑的。在 Web 应用中,MVC 模式的使用已经广为人知,若是 Spring 没有本身实现的 MVC 模式的支持,那么做为一个总体解决方法,它是不完整的。 并且对于 Web UI 的开发来讲,这也是一种很是不错的选择。 下面咱们就慢慢来介绍。web

       

MVC 详解

        简    介

        MVC 是 Model(模型)、View(视图)以及 Controller(控制器)的缩写。它是一种经典的软件架构模式。最先由 Trygve Reenskaug 在 1978 年提出,是 施乐帕罗奥多研究中心 (Xerox PARC)在 20 世纪 80 年代为程序语言 Smalltalk 发明的一种软件架构。MVC 模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,而且使程序某一部分的重复利用成为可能。除此以外,此模式经过对复杂度的简化,使程序结构更为直观。软件系统经过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。数据库

        MVC 模式在 UI 设计中使用的很是广泛,在著做《面向模式的软件体系结构》中,开篇就提到了这个模式。这个模式的主要特色是:分离了模型、视图、控制器三种角色,将业务处理从 UI 设计中独立出来,封装到模型和控制器设计中去,使得它们互相之间解耦,从而能够独立扩展而不须要互相依赖。
编程


        架构内容

        在 Java 领域最经典的 MVC 实现方式是:JSP + Servlet + Javabean,虽然,如今已经被 HTML + AJAX + Servlet + JSON + POJO 这样的实现方式所取代。尽管已经有了许多的不一样,但二者本质仍是同样的,咱们就以经典模式进行分析。设计模式

        在最初的 JSP 网页中,像数据库查询语句(SQL query)这样的数据层代码和像 HTML 这样的表示层代码是混在一块儿。虽然经验比较丰富的开发者会将数据从表示层中分离开来,但这样的良好设计一般并非很容易作到的,实现它须要精心地计划以及不断地尝试。而 MVC 能够从根本上强制性地将它们分开,尽管构造 MVC 应用程序须要一些额外的工做,可是它带给咱们的好处是毋庸置疑的。下面是 MVC 的基本原理图:浏览器

        前面已经提过,MVC 模式将一个交换式应用程序分为三个组件: Model、View 以及 Controller。MVC 模式在概念上强调 Model、View、Controller 的分离,各个模块也遵循着由 Controller 来处理消息,Model 控制数据源,View 负责数据显示地职责分离原则,所以在实现上,MVC 模式的 Framework 一般会将 MVC 三个部分分离实现:Model 负责数据访问,较现代的 Framework 都会建议使用独立的数据对象(DTO、POCO、POJO等等)来代替弱类型的集合对象。数据访问的代码会使用 Data Access 的代码或是 ORM-based Framework,也能够进一步使用 Repository Pattern 与 Unit of Works Pattern 来切割数据源的相依性;Controller 负责处理消息,较高级的 Framework 会有一个默认的实现来做为 Controller 的基础,例如 Spring 的 DispatcherServlet 或是 ASP.NET MVC 的 Controller 等,在职者分离原则上,每一个 Controller 负责的部分不一样,所以会将各个 Controller 切割成不一样的文件以利维护;View 负责显示数据,这个部分多为前端应用,而 Controller 会有一个机制将处理的结果 (多是 Model, 集合或是状态等) 交给 View,而后由 View 来决定怎么显示。例如 Spring Framework 使用 JSP 或相应技术,ASP.NET MVC 则使用 Razor 处理数据的显示。其中,Model 部分是它的核心功能,但在使用上仍是颇为讲究的。服务器

        首先,多个 View 能共享一个 Model 。同一个 Web 应用程序会提供多种用户界面,例如用户但愿既可以经过浏览器来收发电子邮件,还但愿经过手机来访问电子邮箱,这就要求 Web 网站同时能提供 Internet 界面或者 WAP 界面。在 MVC 设计模式中, Model 响应用户请求并返回响应数据,View 负责格式化数据并把它们呈现给用户,业务逻辑和表示层分离,同一个 Model 能够被不一样的 View 重用,因此大大提升了代码的可重用性。数据结构

        其次,Controller 是自包含(self-contained)指高独立内聚的对象,与 Model 和 View 保持相对独立,因此能够方便的改变应用程序的数据层和业务规则。例如,把数据库从 MySQL 移植到 Oracle,或者把RDBMS 数据源改变成 LDAP 数据源,只需改变 Model 便可。一旦正确地实现了控制器,无论数据来自数据库仍是 LDAP 服务器,View 都会正确地显示它们。因为 MVC 模式的三个模块相互独立,改变其中一个不会影响其余两个,因此依据这种设计思想能构造良好的少互扰性的构件。架构

        此外,Controller 提升了应用程序的灵活性和可配置性。Controller 能够用来链接不一样的 Model 和 View 去完成用户的需求,也能够构造应用程序提供强有力的手段。给定一些可重用的 Model 、 View 和Controller 能够根据用户的需求选择适当的 Model 进行处理,而后选择适当的的 View 将处理结果显示给用户。app


        适用范围

        由于 MVC 模式强调职责分离,因此在发展 MVC 应用时会产生出不少文件,在 IDE (集成开发环境) 不够成熟时它会是个问题,但在现代主流 IDE 都能使用类对象的信息来组织代码编辑的状况下,多文件早已不是问题,并且 MVC 模式会要求开发者进一步思考应用程序的架构 (Application Architecture),而非用大杂烩的方式开发应用程序,对于应用程序的生命周期以及后续的可扩充与可维护性而言有至关正面的帮助。另外,MVC 职责分离也带来了一个现代软件工程要求的重要特性:可测试性 (Testability),MVC-based 的应用程序在良好的职责分离的设计下,各个部分可独立行使单元测试,有利用与企业内的自动化测试、持续集成 (Continuous Integration) 与持续发行 (Continuous Delivery) 流程集成,减小应用程序改版部署所需的时间。

        MVC 模式的应用程序的目的就是但愿打破以往应用程序使用的大杂烩程序撰写方式,并间接诱使开发人员以更高的架构导向思惟来思考应用程序的设计,所以对于一个刚入门的初学者来讲,架构导向的思考会有必定的门槛,须要较多的实现与练习才能具有相应的能力,大多数的初学者仍是较习惯于大杂烩式的程序撰写,因此可能会对 MVC 模式抱持着排斥或厌恶的心态,然而 MVC (或是其余的Design Patterns) 都是有助于应用程序长远的发展,虽然大杂烩式的程序也能够用来发展长生命周期的应用程序,可是相较于 MVC,大杂烩式的程序在可扩充性和可维护性 (尤为是可测试性) 上会远比 MVC 复杂不少,相反的,MVC 模式的应用程序是在初始开发时期必须先思考并使用软件架构,使得开发时期会须要花较多心力,可是一旦应用程序完成后,可扩充性、可维护性和可测试性反而会由于 MVC 的特性而变得容易。

        所以,MVC 模式在已有众多优秀 Framework 的现代,早就己经没有不适合小型应用的问题,小型的应用仍是能够由 MVC Framework 的应用来获取 MVC 的优势,同时它也能做为将来小型应用扩充到大型应用时的基础与入门砖。若一开始就想要作大型应用,那么 MVC 模式的职责分离以及要求开发的架构思考会更适合大型应用的开发。


Spring MVC 

        框架基础

        根据需求,Spring 提供了一个 Web 框架,它创建在 Spring 的核心概念 —— IoC 的应用上下文之上,并将其扩展到 Web 环境,与中间层应用上下文之间无缝结合。因为 Spring 的分层架构,Spring 中间层上下文也能轻易地集成到各类不一样的 Web 框架中。固然,要达到这样的分层架构,中间层的接口设计就是相当重要的了。

        Spring 和专用 Web 框架(例如 Struts、WebWork 和 Tapestry)之间最根本的区别是:Spring 将它的 Web MVC 框架做为整体方案架构的一部分,所以它被设计为松散耦合,而且无缝地和 Spring 中间层丰富的 IoC 和 AOP 管理功能融为了一体,这也是 Spring MVC 的特色。


        设计目的

        最初的 J2EE Web 层实现一般是:在 JSP 页中包含过多的 Java 脚本(scriptlet),其中混乱地杂合了表达和业务逻辑。它致使的结果是一个不可测试的表现层、使人头痛的重构,以及维护的地狱。即便不是大多数,至少也有许多 J2EE Web 开发者在缺乏经验时实现了这样的应用程序;而更多的人是接手维护和升级了这样的代码,并恼怒地咒骂最初的开发者。

        最原始的以 JSP 为中心的编程模型出自 ASP 和 PHP,这是 1996 年以后流行的两个 Web 编程环境。在这两个环境中,以页面为中心的脚本是仅有的选择,没法轻松实现分开流程控制和视图呈现,也没法轻松地将业务委派给逻辑组件。在 ASP.NET 和 PHP4 以后,它们都有了很大的改进,都为应用程序架构提供了更好的选择,惋惜传统的编程模型仍然有着很大的影响力。

        因此,在一个分层体系的 J2EE 应用程序中,Web 层结构应该比这样的脚本页面更好,这样就能够像中间层组件同样有着可维护性、可测试性和可重用性。                


        实现基础

        Spring MVC 框架是一个基于请求驱动的 Web 框架,而且也使用了前端控制器模式来进行设计,再根据请求映射规则发送给相应的页面控制器(动做/处理器)进行处理。下面是 Spring MVC 处理请求的流程:

        具体执行步骤以下:

                一、首先用户发送请求——前端控制器,前端控制器根据请求信息(如 URL)来决定选择哪个页面控制器进行处理并把请求委托给它,即之前的控制器的控制逻辑部分也就是一、2步骤;

                二、页面控制器接收到请求后,进行功能处理,首先须要收集和绑定请求参数到一个对象,这个对象在 Spring MVC 中叫 命令对象,并进行验证,而后命令对象委托给业务对象进行处理;处理完毕后返回一个 ModelAndView(模型数据和逻辑视图名),也就是三、四、5步骤;

                三、前端控制器收回控制权,而后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染,步骤六、7;

                四、前端控制器再次收回控制权,将响应返回给用户,从8到整个结束。


        核心架构

        为完成以上的具体执行步骤,Spring MVC 将各个角色的职责进行了清晰的划分:前端控制器(DispatcherServlet)、请求处处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器(Validator)、命令对象(Command 命令对象)、表单对象(Form Object 表单对象)。

        它的核心开发步骤是:

                一、DispatcherServlet 在 web.xml 中的部署描述,从而拦截请求到 Spring MVC;

                二、HandlerMapping 的配置,从而将请求映射处处理器;

                三、HandlerAdapter 的配置,从而支持多种类型的处理器;

                四、ViewResolver 的配置,从而将逻辑视图名解析为具体视图技术;

                五、Controller 的配置,从而进行功能处理。


        下面是 Spring MVC 核心架构:

        核心架构的具体步骤以下:

                一、首先用户发送请求——DispatcherServlet,前端控制器收到请求后本身不进行处理,而是委托给其余的解析器进行处理,做为统一访问点,进行全局的流程控制;

                二、DispatcherServlet——HandlerMapping,HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面控制器)对象、多个 HandlerInterceptor 拦截器)对象,经过这种策略模式,很容易添加新的映射策略;

                三、DispatcherServlet——HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持不少类型的处理器;

                四、HandlerAdapter——处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调整真正的处理器的功能处理方法,完成功能处理;并返回一个 ModelAndView 对象(包含 模型数据、逻辑视图名);

                五、ModelAndView 的逻辑视图名——ViewResoler,ViewResoler 将吧逻辑视图名解析为具体的 View,经过这种策略模式,很容易更换其余视图技术;

                六、View——渲染,View 会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个 Map 数据结构,所以很容易支持其余视图技术;

                七、返回控制权给 DispatcherServlet,由 DispatcherServlet 返回响应给用户,到此一个流程结束。


        好了,至此架构方面就讲完了,再往下就是源码分析了。



——水门(2016年3月写于武汉)

相关文章
相关标签/搜索