Spring MVC请求处理流程
对Web应用来说,表示层是不可或缺的重要环节。传统的Struts2框架就是一个优秀的Web框架。除了Struts2框架外,Spring框架也为表示层提供了一个优秀的Web框架,即Spring MVC。由于Spring MVC采用了松耦合可插拔组件结构,因此比其他MVC框架具有更大的扩展性和灵活性。通过注解,Spring MVC使得POJO成为处理用户请求的控制器,无需实现任何接口。
一、环境及准备
Eclipse(http://www.eclipse.org/)
Tomcat9.0.4(http://tomcat.apache.org/)
jdk9.0.4(http://www.oracle.com/technetwork/java/javase/downloads/index.html)
Spring-framework-5.0.4.RELEASE-dist.zip(http://repo.springsource.org/libs-release-local/)
二、创建项目
在Eclipse中,创建一个名为“springmvc-1”的Web项目,并把相关jar包添加到项目的WebContent\WEB-INF\lib路径中,并添加到项目的构建路径中。如下图所示:
项目最终的目录结构,如下图所示:
三、前端控制器DispatcherServlet
在web.xml文件中,配置Spring MVC的前端控制器DispatcherServlet。Spring MVC是基于Servlet的框架,DispatcherServlet是整个Spring MVC框架的核心,它负责接收请求并将其分派给相应的处理器处理,关键配置代码如下:
上述配置的目的在于,让Web容器使用Spring MVC的DispatcherServlet,并通过设置url-pattern为“/”,将所有的URL请求都映射到这个前端控制器DispatcherServlet。在配置DispatcherServlet的时候,通过设置contextConfigLocation参数来指定Spring MVC配置文件的位置,此处使用Spring 资源路径的方式进行指定。
四、创建Spring MVC的配置文件
在项目springmvc-1的src目录下创建Spring MVC配置文件springmvc.xml,在该配置文件中,我们使用Spring MVC最简单的配置方式进行配置,主要配置如下:
在springmvc.xml配置文件中,首先要引入beans、aop、context和mvc命名空间,然后主要完成配置处理器和视图解析器。在springmvc.xml配置文件中,并没有配置处理器映射和处理器适配器,当用户没有配置这两项时,Spring会使用默认的处理器映射和处理器适配器来处理请求。
五、创建Handler处理器(Controller)
在项目的src目录下创建包com.springmvc.controller,在包中创建类HelloController.java,并实现Controller接口中的handleRequest方法,用来处理hello请求,代码如下:
上诉代码中,HelloController是一个实现了Controller接口的控制器,它可以处理一个单一的请求动作。handleRequest是Controller接口必须实现的方法,该方法必须返回一个包含视图名或视图名和模型的ModelAndView对象,该对象既包含视图信息,也包含模型数据信息。这样Spring MVC就可以使用视图对模型数据进行解析。本例返回的模型中包含一个名为“msg”的字符串对象,返回的视图路径为 /ch06/first.jsp,因此,请求将被转发到 ch06路径下的 first.jsp页面。
ModelAndView对象代表Spring MVC中呈现视图界面时所使用的Model(模型数据)和View(逻辑视图名称)。由于Java一次只能返回一个对象,所以ModelAndView的作用就是封装这两个对象,一次返回我们所需要的Model和View。当然,返回的模型和视图也都是可选的,在一些情况下,模型中没有任何数据,那么只返回视图即可,或者只返回模型,让Spring MVC根据请求URL来决定。以后还会对ModelAndView对象进行讲解。
六、创建视图页面
在项目WebContext路径下创建ch06文件夹,在ch06文件夹中创建JSP视图页面first.jsp,并在该视图页面上通过EL表达式输出“msg”中的信息,代码如下:
七、部署项目,启动Tomcat服务器进行测试
将项目springmvc-1发布到Tomcat中,并启动Tomcat服务器,在浏览器地址中访问http://localhost:8080/springmvc-1/hello,其运行效果如下图所示:
从上图可以看到,浏览器中已经显示出了模型对象的字符串信息,控制台窗口中输出了“Hello Springmvc_1”提示,这也就说明程序执行成功。
使用MVC框架就应该遵守MVC思想,MVC框架不赞成浏览器直接访问Web应用的视图页面,用户的所有请求都只应向控制器发送,由控制器调用模型组件、视图组件向用户呈现数据。
八、总结
当用户发送URL请求http://localhost:8080/springmvc-1/hello时,根据web.xml中对DispatcherServlet(前端控制器)的配置,该请求被DispatcherServlet(前端控制器)截获,并根据HandleMapping(处理器映射器)找到处理相应请求的Handler处理器(Controller控制器,这里便是HelloController);Controller处理完成后,返回ModelAndView对象;该对象告诉DispatcherServlet(前端控制器)需要通过哪个视图来进行数据模型的展示,DispatcherServlet(前端控制器)根据视图解析器把Controller返回的逻辑视图名渲染成真正的视图并输出,呈现给用户。
九、深入了解Spring MVC请求处理流程
Spring MVC请求处理流程如下图所示,我们一步一步来看它的处理流程。
(1)用户通过客户端向服务器发起一个request请求,此请求会被前端控制器(DispatcherServlet)拦截。
(2)前端控制器(DispatcherServlet)请求处理器映射器(HandleMapping)去查找处理器(Handler),可以依据XML配置或注解去查找。
(3)处理器映射器(HandleMapping)根据请求的URL找到具体的处理器(Handler),生成处理器对象及处理器拦截器(如果有则生成),并返回给前端控制器。
(4)前端控制器(DispatcherServlet)请求处理器适配器(HandlerAdapter)去执行相应的处理器(Handler,常称为Controller)。
(5)处理器适配器(HandlerAdapter)会调用并执行处理器(Handler),这里的处理器(Handler)指的是程序中编写的Controller类,也被称为后端控制器。请求信息在真正到达处理器(Handler)的处理方法之前的这段时间内,Spring MVC还完成了很多工作。
消息转换:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
数据转换:对请求消息进行数据转换,如String转换成Integer、Double等。
数据格式化:对请求消息进行数据格式化,如将字符串转换成格式化数字或格式化日期等。
数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
(6)处理器(Handler)执行完毕后,也就是Controller执行完毕后,会返回给处理器适配器(HandlerAdapter)一个ModelAndView对象(Spring MVC底层对象),该对象中会包含View视图信息或包含View视图信息和Model数据模型信息。
(7)处理器适配器(HandlerAdapter)接收到ModelAndView对象后,将其返回给前端控制器(DispatcherServlet)。
(8)前端控制器(DispatcherServlet)接收到ModelAndView对象后,选择一个合适的视图解析器(ViewReslover)对视图进行解析。
(9)视图解析器(ViewReslover)解析后,会根据View视图信息配置到相应的视图结果,反馈给前端控制器(DispatcherServlet)。
(10)前端控制器(DispatcherServlet)收到View视图后,进行视图渲染,将模型数据(在ModelAndView对象中)填充到request域。
(11)前端控制器(DispatcherServlet)向用户响应结果。
以上就是Spring MVC的整个请求处理流程,其中用到的组件有前端控制器(DispatcherServlet)、处理器映射器(HandleMapping)、处理器适配器(HandlerAdapter)、Handler处理器(Controller)、视图解析器(ViewReslover)、视图(View)。其中,前端控制器(DispatcherServlet)、处理器映射器(HandleMapping)、处理器映射器(HandleMapping)、视图解析器(ViewReslover)对象的工作是在框架内部执行的,开发人员并不需要关心这些对象内部的实现过程,只需要配置前端控制器(DispatcherServlet),完成Handler处理器(Controller)中的业务处理,并在视图(View)中展示相应信息即可。