2.5 Spring MVC执行的流程
2.5 Spring MVC执行的流程
下面将对开发Spring MVC
应用的过程进行总结,以让读者对Spring MVC
有一个大致的了解。
2.5.1 Spring MVC应用的开发步骤
下面简单介绍 Spring MVC应用的开发步骤。
1 web.xml中定义前端控制器
在web.xml
文件中定义前端控制器DispatcherServlet
来拦截用户请求。
由于Web
应用是基于请求/响应架构的应用,所以不管哪个MVC Web
框架,都需要在web.xml
中配置该框架的核心Servlet
或Filter
,这样才可以让该框架介入Web
应用。
例如,开发Spring MVC
应用的第1步
就是在web.xml
文件中增加如下配置片段:
1 | <!-- 定义前端控制器 --> |
2 定义包含表单数据的JSP页面
如果需要以POST
方式提交请求,则定义包含表单数据的JSP
页面。如果仅仅只是以GET
方式发送请求,则无须经过这一步。
3 定义处理用户请求的Handle类
定义处理用户请求的Handle
类,该类可以实现Controller
接口或使用@Controller
注解来实现。这一步也是所有MVC
框架中必不可少的,因为这个DispatcherServlet
就是MVC中的C,也就是前端控制器,该控制器负责接收请求,并将请求分发给对应的Handle
类,该Handle
类负责调用后台业务逻辑代码来处理请求。
创建Controller实例 调用其方法来处理请求
可能有读者会产生疑问: Controller
并未接收到用户请求,它怎么能够处理用户的请求呢?MVC
框架的底层机制是:前端控制器DispatcherServlet
接收到用户请求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Controller
实例,并调用Controller
的指定方法来处理用户请求:
- 如果是实现
Controller
接口的Controller
,则调用的是handlRequest
方法, - 如果是使用基于注解的控制器,则可以调用任意方法
如何知道创建哪个Controller接口的实例
这里又产生了一个问题:当Servlet
拦截用户请求后,它如何知道创建哪个Controller
接口的实例呢?
有两种解决方案:
- 利用
xml
配置文件:例如在xml
配置文件中描述hello
请求对应使用HelloController
类。这就可以让MVC
框架知道当接收到hello
请求时要创建哪个Controller
接口的实例。 - 利用注解:例如使用注解
@Controller
描述一个类,并使用注解@RequestMapping(value="/hello")
描述hello
请求对应的方法。这样也可以让MVC
框架知道要创建哪个Controller
接口的实例并调用哪个方法处理请求。
控制器分类
根据上面的介绍不难发现,在Spring MVC
框架中,控制器实际上由两个部分组成:
- 即拦截所有用户请求和处理请求的通用代码都由前端控制器
DispatcherServlet
完成, - 而实际的业务控制(调用后台业务逻辑代码,返回处理结果等)则由
Controller
处理。
4 配置Handle
使用xml配置Handle
Java
领域的绝大部分MVC
框架都非常喜欢使用xml
文件来进行配置管理,这在以前是一种思维定势。即配置哪个请求对应哪个Controller
,从而让前端控制器根据该配置来创建合适的Controller
实例,并调用该Controller
的业务控制方法。
例如,可以采用如下代码片段来配置Handle
:
1 | <!-- 配置Handle,映射"/hello"请求 --> |
使用注解来配置Handle
在Spring2.5
之后,推荐使用注解来配置Handle
:
1 | package org.fkit.controller; |
上面的配置片段指定如果用户请求URL
为hello
,则使用org.fkit.controller.Hellocontroller
来处理。现在几乎所有的MVC
框架都使用”约定优于配置”的思想,也就是采用约定方式来规定用户请求地址和Handle
之间的对应关系。
5 编写视图资源
当Handle
处理用户请求结束后,通常会返回一个ModelAndView
对象,该对象中应该包含返回的视图名或视图名和模型,这个视图名就代表需要显示的物理视图资源。如果Handle
需要把一些数据传给视图资源,则可以通过模型对象实现。
经过上面5个步骤,即可基本完成一个Spring MVC
处理流程的开发,也就是可以执行一次完整的请求→响应
过程。
2.5.2 Spring MVC执行的流程
上一节所介绍的Spring MVC
应用的开发流程实际上是按请求→响应
的流程来开发的,下面通过一个流程图来介绍请求→响应
的完整流程。图2.5显示了一次请求→响应的完整流程。
Spring MVC 请求响应工作流程
按安照图2.5中所标识的序号, Spring MVC
请求→响应的完整工作流程如下
- 用户向服务器发送请求,请求被
Spring
的前端控制器DispatcherServlet
截获。 DispatcherServlet
对请求URL
(统一资源定位符)进行解析,得到URI
(请求资源标识符)。然后根据该URI
,调用HandlerMapping
获得该Handler
配置的所有相关的对象,包括Handler
对象以及Handler
对象对应的拦截器
,这些对象会被封装到一个HandlerExecutionChain
对象当中返回。DispatcherServlet
根据获得的Handler
,选择一个合适的HandlerAdapter
。HandlerAdapter
会被用于处理多种Handler
,调用Handler
实际处理请求的方法,例如hello
方法。- 提取请求中的模型数据,开始执行
Handler(也就是Controller)
。在填充Handler
的入参过程中,根据配置Spring
将帮你做一些额外的工作:
- 消息转换。将请求消息(如
JSON
、XML
等数据)转换成一个对象,将对象转换为指定的响应信息。 - 数据转换。对请求消息进行数据转换,如
String
转换成Integer
、Double
等。 - 数据格式化。对请求消息进行数据格式化,如将字符串转换成格式化数字或格式化日期等。
- 数据验证。验证数据的有效性(长度、格式等),验证结果存储到
BindingResult
或Error
中。
handler
执行完成后,向DispatcherServlet
返回一个ModelAndView
对象,ModelAndView
对象中应该包含视图名
或视图名和
模型.- 根据返回的
ModelAndView
对象,选择一个合适的ViewResolver
(视图解析器)返回给DispatcherServlet
ViewResolver
结合Model
和View
来渲染视图。- 将视图渲染结果返回给客户端。
只需要开发Handler即可
以上8个步骤, DispatcherServlet
、 HandlerMapping
、 HandlerAdapter
和ViewResolver
等对象协同工作,来完成Spring MVC
请求→响应的整个工作流程,这些对象所完成的工作对于开发者来说都是不可见的,开发者并不需要关心这些对象是如何工作的,开发者只需要在Handler(也就是Controller)
当中完成对请求的业务处理。
提示关于DispatcherServlet
、 HandlerMapping
、 HandlerAdapter
和ViewResolver
等对象协同工作的知识,对于还不了解Spring MVC
的读者来说,可能会感觉很难理解,因为这一节的知识涉及Spring MVC
的源代码和Spring MVC
的设计思想,建议初学者学习完Spring MVC
的知识之后再回过头来看本节的内容。