在Web世界里,具体步骤以下:
1、 Web阅读器(如IE)发起要求,如访问http://sishuok.com
2、 Web服务器(如Tomcat)接收要求,处理要求(比如用户新增,则将把用户保存1下),最后产生响应(1般为html)。
3、web服务器处理完成后,返回内容给web客户端(1般就是我们的阅读器),客户端对接收的内容进行处理(如web阅读器将会对接收到的html内容进行渲染以展现给客户)。
因此,在Web世界里:
都是Web客户端发起要求,Web服务器接收、处理并产生响应。
1般Web服务器是不能主动通知Web客户端更新内容。虽然现在有些技术如服务器推(如Comet)、还有现在的HTML5 websocket可以实现Web服务器主动通知Web客户端。
到此我们了解了在web开发时的要求/响应模型,接下来我们看1下标准的MVC模型是甚么。
MVC模型:是1种架构型的模式,本身不引入新功能,只是帮助我们将开发的结构组织的更加公道,使展现与模型分离、流程控制逻辑、业务逻辑调用与展现逻辑分离。如图1⑵
图1⑵
首先让我们了解下MVC(Model-View-Controller)3元组的概念:
Model(模型):数据模型,提供要展现的数据,因此包括数据和行动,可以认为是领域模型或JavaBean组件(包括数据和行动),不过现在1般都分离开来:Value Object(数据) 和 服务层(行动)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展现,1般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户要求,拜托给模型进行处理(状态改变),处理终了后把返回的模型数据返回给视图,由视图负责展现。 也就是说控制器做了个调度员的工作,。
从图1⑴我们还看到,在标准的MVC中模型能主动推数据给视图进行更新(视察者设计模式,在模型上注册视图,当模型更新时自动更新视图),但在Web开发中模型是没法主动推给视图(没法主动更新用户界面),由于在Web开发是要求-响应模型。
那接下来我们看1下在Web里MVC是甚么模样,我们称其为 Web MVC 来区分标准的MVC。
模型-视图-控制器概念和标准MVC概念1样,请参考1.2,我们再看1下Web MVC标准架构,如图1⑶:
如图1⑶
在Web MVC模式下,模型没法主动推数据给视图,如果用户想要视图更新,需要再发送1次要求(即要求-响应模型)。
概念差不多了,我们接下来了解下Web端开发的发展历程,和使用代码来演示1下Web MVC是如何实现的,还有为何要使用MVC这个模式呢?
此处我们只是简单的叙述比较核心的历程,如图1⑷
图1⑷
1.4.1、CGI:(Common Gateway Interface)公共网关接口,1种在web服务端使用的脚本技术,使用C或Perl语言编写,用于接收web用户要求并处理,最后动态产生响应给用户,但每次要求将产生1个进程,重量级。
1.4.2、Servlet:1种JavaEE web组件技术,是1种在服务器端履行的web组件,用于接收web用户要求并处理,最后动态产生响应给用户。但每次要求只产生1个线程(而且有线程池),轻量级。而且能利用许多JavaEE技术(如JDBC等)。本质就是在java代码里面 输出 html流。但表现逻辑、控制逻辑、业务逻辑调用混杂。如图1⑸
图1⑸
如图1⑸,这类做法是绝对不可取的,控制逻辑、表现代码、业务逻辑对象调用混杂在1起,最大的问题是直接在Java代码里面输出Html,这样前端开发人员没法进行页面风格等的设计与修改,即便修改也是很麻烦,因此实际项目这类做法不可取。
1.4.3、JSP:(Java Server Page):1种在服务器端履行的web组件,是1种运行在标准的HTML页面中嵌入脚本语言(现在只支持Java)的模板页面技术。本质就是在html代码中嵌入java代码。JSP终究还是会被编译为Servlet,只不过比纯Servlet开发页面更简单、方便。但表现逻辑、控制逻辑、业务逻辑调用还是混杂。如图1⑹
图1⑹
如图1⑹,这类做法也是绝对不可取的,控制逻辑、表现代码、业务逻辑对象调用混杂在1起,但比直接在servlet里输出html要好1点,前端开发人员可以进行简单的页面风格等的设计与修改(但如果嵌入的java脚本太多也是很难修改的),因此实际项目这类做法不可取。
JSP本质还是Servlet,终究在运行时会生成1个Servlet(如tomcat,将在tomcat\work\Catalina\web利用名\org\apache\jsp下生成),但这类使得写html简单点,但还是控制逻辑、表现代码、业务逻辑对象调用混杂在1起。
1.4.4、Model1:可以认为是JSP的增强版,可以认为是jsp+javabean如图1⑺
特点:使用<jsp:useBean>标准动作,自动将要求参数封装为JavaBean组件;还必须使用java脚本履行控制逻辑。
图1⑺
此处我们可以看出,使用<jsp:useBean>标准动作可以简化javabean的获得/创建,及将要求参数封装到javabean,再看1下Model1架构,如图1⑻。
图1⑻ Model1架构
Model1架构中,JSP负责控制逻辑、表现逻辑、业务对象(javabean)的调用,只是比纯JSP简化了获得要求参数和封装要求参数。一样是不好的,在项目中应当严禁使用(或最多再demo里使用)。
1.4.5、Model2:在JavaEE世界里,它可以认为就是Web MVC模型
Model2架构其实可以认为就是我们所说的Web MVC模型,只是控制器采取Servlet、模型采取JavaBean、视图采取JSP,如图1⑼
图1⑼ Model2架构
具体代码事例以下:
从Model2架构可以看出,视图和模型分离了,控制逻辑和展现逻辑分离了。
但我们也看到严重的缺点:
1. 1、控制器:
1.1.1、控制逻辑可能比较复杂,其实我们可以依照规约,如要求参数submitFlag=toAdd,我们其实可以直接调用toAdd方法,来简化控制逻辑;而且每一个模块基本需要1个控制器,造成控制逻辑可能很复杂;
1.1.2、要求参数到模型的封装比较麻烦,如果能交给框架来做这件事情,我们可以从中得到解放;
1.1.3、选择下1个视图,严重依赖Servlet API,这样很难或基本不可能更换视图;
1.1.4、给视图传输要展现的模型数据,使用Servlet API,更换视图技术也要1起更换,很麻烦。
1.2、模型:
1.2.1、此处模型使用JavaBean,可能造成JavaBean组件类很庞大,1般现在项目都是采取3层架构,而不采取JavaBean。
1.3、视图
1.3.1、现在被绑定在JSP,很难更换视图,比如Velocity、FreeMarker;比如我要支持Excel、PDF视图等等。
1.4.5、服务到工作者:Front Controller + Application Controller + Page Controller + Context
即,前端控制器+利用控制器+页面控制器(也有称其为动作)+上下文,也是Web MVC,只是责任更加明确,详情请参考《核心J2EE设计模式》和《企业利用架构模式》如图1⑴0:
图1⑴0
运行流程以下:
职责:
Front Controller:前端控制器,负责为表现层提供统1访问点,从而避免Model2中出现的重复的控制逻辑(由前端控制器统1回调相应的功能方法,如前边的根据submitFlag=login转调login方法);并且可以为多个要求提供共用的逻辑(如准备上下文等等),将选择具体视图和具体的功能处理(如login里边封装要求参数到模型,并调用业务逻辑对象)分离。
Application Controller:利用控制器,前端控制器分离选择具体视图和具体的功能处理以后,需要有人来管理,利用控制器就是用来选择具体视图技术(视图的管理)和具体的功能处理(页面控制器/命令对象/动作管理),1种策略设计模式的利用,可以很容易的切换视图/页面控制器,相互不产生影响。
Page Controller(Command):页面控制器/动作/处理器:功能处理代码,搜集参数、封装参数到模型,转调业务对象处理模型,返回逻辑视图名交给前端控制器(和具体的视图技术解耦),由前端控制器拜托给利用控制器选择具体的视图来展现,可以是命令设计模式的实现。页面控制器也被称为处理器或动作。
Context:上下文,还记得Model2中为视图准备要展现的模型数据吗,我们直接放在request中(Servlet API相干),有了上下文以后,我们就能够将相干数据放置在上下文,从而与协议无关(如Servlet API)的访问/设置模型数据,1般通过ThreadLocal模式实现。
到此,我们回顾了全部web开发架构的发展历程,可能不同的web层框架在细节处理方面不同,但的目的是1样的:
干净的web表现层:
模型和视图的分离;
控制器中的控制逻辑与功能处理分离(搜集并封装参数到模型对象、业务对象调用);
控制器中的视图选择与具体视图技术分离。
轻浮的web表现层:
做的事情越少越好,薄薄的,不应当包括无关代码;
只负责搜集并组织参数到模型对象,启动业务对象的调用;
控制器只返回逻辑视图名并由相应的利用控制器来选择具体使用的视图策略;
尽可能少使用框架特定API,保证容易测试。
到此我们了解Web MVC的发展历程,接下来让我们了解下Spring MVC究竟是甚么、架构及来个HelloWorld了解下具体怎样使用吧。