admin管理员组文章数量:1794759
Spring MVC体系结构(一)
前言
此文章可以带领初学者们搭建Spring MVC项目,文中对MVC模式、Spring MVC的诞生背景、原理、体系结构等做了讲解,并以一个例子帮助理解。此博文中的所有图片,均是博主用脑图工具手动画的(网上的太不清晰了,不好找),转载请标明出处!
目录
前言
一、MVC设计模式杂谈
第一种:JSP Model1
第二种:JSP Model2
MVC处理流程及优缺点
二、Spring MVC介绍及其环境搭建
一、Spring MVC框架介绍
二、Spring MVC环境搭建
三、Spring MVC框架的请求处理流程及体系结构
一、Spring MVC框架的请求处理流程
二、Spring MVC框架的体系结构
三、Spring MVC框架的特点
总结
一、MVC设计模式杂谈
在传统的Web应用开发中,我们的架构模式基本一致:
- 数据实体:POJO
- 数据层:DAO
- 业务层:Service
- 控制层:Servlet
- 表示层(页面层):JSP页面或HTML页面
这种架构模式就是MVC设计模式,它是软件工程中的一种架构模式,强制性地使软件系统的输入、处理和输出分开,把系统分为三个基本部分:模型(Model)、视图(View)、控制器(Controller),如下图所示:
结合上图,我们分析一下MVC模式中各部分的职责:
Model:模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务逻辑)的处理和实现数据库的操作。在项目中除了控制层的控制器,几乎每一个Bean组件都属于模型,比如Service层、DAO层,以及POJO实体类等。
View:负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、页面设计等功能。说白了就是离用户最近的、展示给人们看的,比如HTML或者JSP页面。
Controller:负责接收并转发请求,对请求处理之后拿到响应结果,指派要使用的视图(类似于指定Servlet跳转到不同的页面进行展示),将响应结果返回给客户端。对应的组件一般是Servlet,很少用JSP页面直接处理其他页面过来的请求。
其实,JavaBean+Servlet+JSP,就是最经典的MVC。下面看一下MVC的两种模式:
第一种:JSP Model1在一个项目中,如果业务流程比较简单的时候,可以把控制器的功能交给视图,项目架构中只有视图和模型,没有控制器,即JSP+JavaBean,这种模式称为JSP Model1。
通过上图我们可以发现,Model1模式的基础是JSP,它由JSP和JavaBean组成,JSP从HTTPRequest中获取所需要的数据,并调用JavaBean进行业务逻辑的处理,然后通过HTTPResponse将结果返回给前端浏览器。可见,Model1一定程度上实现了MVC,只不过将控制层和视图层统一定位到JSP页面,JavaBean依然充当模型组件。这种模式下JSP身兼多职,既要负责视图层的数据展示,又要负责业务流程控制,结构较为混乱,也不是我们所希望的松耦合架构,所以在大型项目中或者当业务流程比较复杂的时候不建议这样做。
第二种:JSP Model2相比于JSP Model1,当业务流程比较复杂的时候,就需要把业务流程控制交给专门的控制器,JSP只专注于视图的渲染展现即可。这种模式就是JSP Model2,即JSP+Servlet+JavaBean,也就是典型的MVC设计模式。
相比于Model1,Model2是将控制层单独划分出来,以Servlet的形式存在于项目架构中,负责业务流程的控制,接收请求,创建所需的JavaBean组件,并将处理后的数据返回给视图(JSP/HTML)进行结果渲染展示。这样的结构比较清晰,效果明显优化很多,并且结合Spring的IoC和AOP,也是一个松耦合的架构模式。所以,除非项目特别简单,一般情况下推荐使用JSP Model2。
MVC处理流程及优缺点通过以上对MVC的了解,我们不妨分析一下MVC的处理过程:
以上即是MVC的处理流程以及各部分之间的关系,那么任何一件事都会有利有弊,我们再分析一下MVC模式的优缺点。
优点:
缺点:
总之,我们可以通过MVC的设计模式,最终打造出一个松耦合+高复用+高适用性等的完美架构,这也是架构设计的目标之一。但是,对于MVC来说,它并不适用于小型的项目,花费大量的时间将MVC应用到项目中通常得不偿失,夸张点说,可能搭建三层架构、构建MVC开发环境的时间,都可以实现整个项目功能了。所以,是否使用MVC模式,应该根据实际场景来决定。
二、Spring MVC介绍及其环境搭建 一、Spring MVC框架介绍有了以上对MVC设计模式的认识,将有助于我们理解Spring MVC的理念与原理。
Spring MVC是Spring家族中应用于Web应用的一个模块,是Spring提供的一个基于MVC设计模式的Web开发框架,可以将它理解为Servlet。在MVC模式中,Spring MVC作为控制器(Controller)来建立模型与视图的数据交互,是结构最清晰的JSP Model2实现,可以说是一个典型的MVC框架。
除此之外,Spring MVC框架采用松耦合、可插拔的组件结构,具有高度可配置性,比起其他的MVC框架更具有扩展性和灵活性。并且它本身就是Spring家族的一部分,与Spring框架整合更是天衣无缝。
在Spring MVC框架中,Controller替换Servlet来担负控制器的职责。Controller接收请求,调用相应的Model进行处理,Model处理完之后将结果返回给Controller,Conreoller再指派相应的View对处理结果进行渲染,最终响应给客户端进行展示。
由于Spring MVC结构较复杂,以上只是简单的介绍,接下来我们以一个例子,来搭建Spring MVC环境,从而更深入的了解它的架构模型及请求处理流程。万变不离其宗,依然以编程界的圣经——“Hello World”为例。
二、Spring MVC环境搭建首先创建Web项目,在项目根目录创建resource文件夹,待会存放我们的配置文件,并创建以下目录结构:
1、准备需要的jar包
本基础示例所需要的jar包如下:
没有的请自行下载,分享百度网盘下载地址(5.0.8版本):
pan.baidu/s/1HYqfU85-jPkHmDJeUFoWHA
2、在web.xml中配置Servlet
Spring MVC是基于Servlet的,DispatcherServlet是整个Spring MVC框架的核心,它负责截获请求并将其分派给相应的处理器。那么搭建Spring MVC环境,首先我们要进行DispatcherServlet的配置。同之前配置Servlet一样,因为通过读取源码我们可以发现,DispatcherServlet这个类继承了FrameworkServlet,FrameworkServlet又继承了HttpServletBean,HttpServletBean最终继承了HttpServlet,所以可以说DispatcherServlet本身就是一个Servlet。
在web.xml配置如下:
<web-app> <servlet> <servlet-name>mvcDemo</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!--指定SpringMVC配置文件的路径--> <param-value>classpath:spring-mvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <!--告诉容器一开始就加载此Servlet--> </servlet> <servlet-mapping> <servlet-name>mvcDemo</servlet-name> <url-pattern>/</url-pattern> <!--截获所有的HTTP请求--> </servlet-mapping> </web-app>在上述代码中,配置了一个名为mvcDemo的Servlet。该Servlet是DispatcherServlet类型,前面已经介绍过Sprnig MVC本质就是一个Servlet,它是Spring MVC的入口,并通过<load-on-startup>1</load-on-startup>指定容器在启动的时候就创建此Servlet,然后通过servlet-mapping映射到“/”,即所有的URL请求都会被该Servlet截获。
最重要的一点,我们需要设置一个参数contextConfigLocation参数来指定Spring MVC配置文件的路径(我们马上就创建),此处使用资源路径的方式进行指定(classpath:……)。这个参数也可以声明成上下文参数,保证能读取到就行。
3、创建Spring MVC的配置文件
在resource文件夹下创建spring-mvc-servlet.xml配置文件(为了方便与其他框架的集成的时候,各个配置文件能够更好的区分,建议采用此命名规范,当然这个因人而异),内容如下:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="www.springframework/schema/beans" xmlns:xsi="www.w3/2001/XMLSchema-instance" xmlns:mvc="www.springframework/schema/mvc" xmlns:p="www.springframework/schema/p" xmlns:context="www.springframework/schema/context" xsi:schemaLocation="www.springframework/schema/beans www.springframework/schema/beans/spring-beans.xsd www.springframework/schema/context www.springframework/schema/context/spring-context.xsd www.springframework/schema/mvc www.springframework/schema/mvc/spring-mvc.xsd "> <bean name="/welcome" class="com.smbms.controller.WelcomeController" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>在上述配置文件,主要包含两部分内容:
1)配置处理器映射
我们在web.xml中配置DispatcherServlet时,配置了所有请求都由此Servlet来处理,那么DispatcherServlet怎么判断它将哪个请求、分发给哪个Controller(控制器)去处理呢?DispatcherServlet需要咨询一个Bean组件,这个Bean叫做HandlerMapping,它的作用就是将一个URL请求映射到相应的Controller,类似于servlet-mapping中的url-pattern。
Spring MVC提供了多种处理器映射(HandlerMapping)的支持,如:
- org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
- org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
- org.springframework.web.servlet.mvc.annotation.DefaultAnnontationHandlerMapping;
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,等
可以根据需求选择处理器映射,此处我们采用BeanNameUrlHandlerMapping(默认的),即在Spring容器中查找与请求URL相同名称的Bean。这个映射器不需要配置,根据请求的URL路径映射到控制器Bean的名称。至于其他的处理器映射,在以后相继介绍。
<bean name="/welcome" class="com.smbms.controller.WelcomeController" />指定这个Bean的类型是我们目录结构下controller包下的WelcomeController类,让这个类作为一个控制器,URL是/welcome的请求将被这个控制器处理。当然,到这一步我们还没有创建这个类,不要急,下一步我们就创建它(本人喜欢从配置文件入手)。
2)配置视图解析器
处理请求的最后一件必要的事情就是渲染输出,返回给客户端显示,这个任务由视图(View)实现。那么就需要确定指定的请求需要哪个视图进行渲染?DispatcherServlet会查找到一个视图解析器,将控制器返回的逻辑视图名称转换成实际视图。Spring也提供了多种视图解析器,如下:
- org.springframework.web.servlet.view.InternalResourceViewResolver;
- org.springframework.web.servlet.view.ContentNegotiatingViewResolve,等等
此处我们使用InternalResourceViewResolver定义该视图解析器,通过配置prefix(前缀)和suffix(后缀),最后将视图逻辑名解析为/jsp/xxx.jsp,即定位到jsp文件夹下的.jsp文件。
4、创建Controller
到这一步,Spring MVC的环境已经搭建好了,我们只需要再填入一点缺失的东西,即Controller和View。我们先创建Controller。
在com.smbms.controller目录下新建WelcomeController.java文件,即我们上面配置的处理器映射。如何将一个JavaBean变成可以处理前端请求的控制器?需要继承org.springframework.web.servlet.mvc.AbstractController,并实现其handleRequestInternal方法,代码如下:
package com.smbms.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class WelcomeController extends AbstractController { @Override protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { return new ModelAndView("welcome"); } }上述代码中,控制器处理方法的返回值为ModelAndView对象,该对象既包含视图信,也包含模型数据信,这样Spring MVC就可以使用视图对模型数据进行渲染。其中“welcome”就是视图的逻辑名,最后由视图解析器处理就会变成/jsp/welcome.jsp。因为我们这个例子并不返回数据给页面,所以Model为空,不进行设置。
说点题外话,ModelAndView,正如其名所示,它代表Spring MVC中呈现视图界面时所使用的Model(模型数据)和View(逻辑视图名)。由于Java一次只能返回一个对象,所以ModelAndView的作用就是封装这两个对象,以方便一次返回我们所需的Model和View。当然,返回的模型跟视图都是可选的,有时候模型中没有任何数据,那么只返回视图即可;或者只返回模型数据,让Spring MVC根据请求URL来决定视图。在以后会对ModelAndView对象进行更详细的讲解。
5、创建View
上面刚说过,我们的Controller返回的逻辑视图名被解析之后,会转换成/jsp/welcome.jsp,所以我们需要在jsp文件夹下存在welcome.jsp文件。在这之前,我们先创建一个main.jsp,作为请求发起的入口(当然你也可以在启动服务之后直接在地址栏访问)。
main.jsp内容如下:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <a href="../welcome">去拜访Spring MVC大爷</a> <%--因为是在jsp目录下,所以先返回上一级目录,回到根目录--%> </body> </html>然后创建welcome.jsp:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Hello World</h1> <p>来自Spring MVC大爷的回复</p> </body> </html>6、部署运行
部署你的项目到Tomcat容器,启动项目,点击按钮,如下
通过上述示例,我们简单总结一下Spring MVC的处理流程:
当用户发起URL请求localhost:8088/welcome时,根据web.xml中对于DispatcherServlet的配置,该请求被DispatcherServlet所截获,并根据HandlerMapping找到处理此次请求的相应的Controller(WelcomeController),Controller处理完成之后返回ModelAndView对象,该对象告诉DispatcherServlet需要通过哪个视图来进行数据模型的渲染展示,然后DispatcherServlet拿着这个返回的视图名称去找视图解析器,转换成真正的View(即/jsp/welcome.jsp),返回给浏览器客户端。
7、优化HandlerMapping(处理器映射)
在以上的示例中,我们通过BeanNameUrlHandlerMapping的方式实现请求与Controller之间的映射,但是如果有多种请求,岂不是要在spring-mvc-servlet中配置多个映射关系?针对这种问题,Spring MVC提供了一键式配置方法:<mvc:annotation-driven />,通过注解的方式定义Controller,下面就对以上示例进行优化,结合实例来理解。
修改spring-mvc-servlet.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="www.springframework/schema/beans" xmlns:xsi="www.w3/2001/XMLSchema-instance" xmlns:mvc="www.springframework/schema/mvc" xmlns:p="www.springframework/schema/p" xmlns:context="www.springframework/schema/context" xsi:schemaLocation="www.springframework/schema/beans www.springframework/schema/beans/spring-beans.xsd www.springframework/schema/context www.springframework/schema/context/spring-context.xsd www.springframework/schema/mvc www.springframework/schema/mvc/spring-mvc.xsd "> <context:component-scan base-package="com.smbms.controller" /> <mvc:annotation-driven /> <!--<bean name="/welcome" class="com.smbms.controller.WelcomeController" />--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>我们更改了Spring MVC的处理器映射的配置为支持注解式处理器——配置<mvc:annotation-driven />标签。它是Spring MVC提供的一种配置方法,配置此标签之后Spring MVC会帮我们做一些注册组件之类的事,它会根据注解定义的Controller中的处理方法所定义的URL请求路径,自动为我们做URL和Controller之间的映射。具体的实现是,这个标签会自动注册DefaultAnnotationHandlerMapping(处理器映射)和AnnotationMethodHandlerAdapter(处理器适配器),Spring MVC会通过这两个实例完成对@Controller和@RequestMapping等注解的支持,从而找出URL与handler method的关系并予以关联。不是很明白没关系,以后会一点点的推进讲解,更深入地了解它。
然后我们添加了<context:component-scan>标签来扫描我们的controller包,找出使用注解定义的Bean组件,加载到Spring容器,这一点是之前说过的知识点,不再解释。
修改完了配置文件,再去我们的控制器做修改,将WelcomeController.java修改为以下内容:
package com.smbms.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class WelcomeController{ @RequestMapping("/welcome") //表示与哪个URL请求相对应 public String welcome(){ return "welcome"; } }在之前讲解使用注解定义Bean组件的时候说过,@Controller用于定义控制层的组件。这里我们使用@Controller注解将我们的WelcomeController类定义为一个控制器,使其成为一个可以处理HTTP请求的控制器,再使用@RequestMapping注解对它的方法进行标注,确定welcome()方法对应的请求URL,即说明URL为/welcome的请求都将由这个方法进行处理。
这样一来,如果还有其他的业务需求,若不是很复杂,那么就可以直接在该类下增加相应的方法即可,然后再为方法标注@RequestMapping。这样无须创建很多个JavaBean作为Controller,这也是我们经常用的一种方式,支持注解式的处理器。
重新运行项目,与之前的结果是一样的。
注:<mvc:annotation-driven />的原理实现在以后会详解,这里只需要会用就行。
三、Spring MVC框架的请求处理流程及体系结构 一、Spring MVC框架的请求处理流程通过上面的一个小示例,我们了解了Spring MVC环境的搭建,接下来再深入了解一下它的处理流程。
分析这张图,可以发现Spring MVC也是一个基于请求驱动的Web框架,并且也使用了前端控制器模式来进行设计,再根据请求映射规则分发给相应的页面控制器(处理器)来进行处理,下面具体分析一下它的处理步骤:
根据上述的请求处理流程,我们继续了解下Spring MVC的体系结构。
通过上图我们发现,从接收请求到返回响应,Spring MVC框架的众多组件通力配合、各司其职地完成整个流程工作。在整个框架中,Spring MVC通过一个前端控制器接收所有的请求,并将具体工作委托给其他组件进行处理,所以说DispatcherServlet处于核心地位,它负责协调组织不同组件完成请求处理并返回响应结果。
根据Spring MVC的请求处理过程,我们具体分析一下每个组件所负责的工作内容:
以上是关于Spring MVC的体系结构的分析,我们可以体会到其设计的精妙之处。在后续的博文中,会陆续围绕着它的整个体系结构进行深入讲解。
三、Spring MVC框架的特点通过上文的演示示例以及对Spring MVC的处理流程、体系结构的介绍,我们可以总结一下它的特点:
- 角色划分清晰。Model、View、Controller各司其职,耦合度较低。
- 灵活的配置功能。Spring的核心是IoC和AOP,统一可以实现在MVC上,把各种类当作Bean组件配置在Spring容器中。
- 提供了大量的接口和实现类,方便各种场景的开发。
- 真正做到与View层的实现无关。
- 结合Spring的依赖注入,更好地应用了面向接口编程的思想。
- 可以与Spring天衣无缝的整合
- 等等
总之,关于Spring家族的框架,对开发者来说都是一种不错的选择。
总结Spring MVC结构比较复杂,学习的时候也要掌握方法。首先要明确Spring MVC是一个工具,既然是工具,那么就先学会它的使用方法,不要深陷其细节中,不建议刚开始学习就研究源码,深入浅出,慢慢地在使用过程中加深理解,最后看透源码自然会水到渠成。
版权声明:本文标题:Spring MVC体系结构(一) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686617008a86693.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论