Spring mvc 请求处理

参考文章:
https://www.jianshu.com/p/6dadc489969a
http://www.cnblogs.com/dreamworlds/p/5396112.html
http://www.jianshu.com/p/baa3a05cd271
http://blog.csdn.net/binglumeng/article/details/53585821
本篇文章从以上几篇文章中提取出认为比较易懂的东西,另外加了一些自己项目里的内容。主要用于记录自己阶段的理解。

Spring MVC工作流程如下:
Spring mvc 请求处理_第1张图片
Spring mvc 请求处理_第2张图片
Spring工作流程如上图所示:
1.用户向服务器发送请求,请求被Spring前端控制Servlet DispatcherServlet捕获;
2.DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3.DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。(如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法);
4.提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler入参的过程中,根据你的配置,Spring帮你完成如下工作:
  HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
  数据转换:对请求消息进行数据转化。如String转化成Integer、Double等;
  数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
5.Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象;
6.根据返回的ModelAndView,选择一个合适的ViewResolver返回给DispatcherServlet;
7.ViewResolver结合Model和View,来渲染视图;
8.将渲染结果返回给客户端。

为什么Spring只使用一个Servlet(DispatcherServlet)来处理所有请求?
主要原因由于J2EE核心模式-Font Controller(前端控制器)。Front Controller模式要求在WEB应用系统的前端(Front)设置一个入口控制器(Controller),所有的request请求都被发往该控制器统一处理。Front Controller一般可以用来做一共同处理比如认证,页面导航,Session管理,国际化或本地化处理等。在开发WEB应用系统(但不拘于WEB应用)时,存在很多不恰当的设计方法,比如让客户端(Client,一般指浏览器)可以直接访问各个视图(view,JSP等)。这样逻辑被分散到各个视图中,从而产生了各种问题:
1》对已有的功能修改困难,可维护性低。假如session管理,一旦session内容需要发生改变,则需要修改所有view中的相关代码。
2》很难增加新的功能,缺乏可扩展性。例如,需要在已有的系统中加入安全控制功能,控制用户对某些页面的访问,因为没有统一的处理入口,需要在所有的view中都加上认证代码。
使用Front Controller,强制分离view的显示逻辑与业务处理逻辑。

DispatchServlet项目工程中配置的补充:

<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:config/servlet-context.xml</param-value>
		</init-param>
		<init-param>
			<param-name>detectAllHandlerExceptionResolvers</param-name>
			<param-value>false</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

当Tomcat或者jetty加载web.xml时,1.先访问 < servlet-mapping > 中的< url-pattern >/< /url-pattern >,其中 / 表示的是http://localhost:8080/ + 工程名;2.执行< servlet-name>appServlet< /servlet-name>3.执行< servlet>
< servlet-name>appServlet< /servlet-name>
4.执行< servlet-class>org.springframework.web.servlet.DispatcherServlet< /servlet-class>
注意:

  • url-pattern 标签中的值是要在浏览器地址栏中输入的 url,可以自己命名,这个 url 访问名为 servlet-name
    中值的 servlet,两个 servlet-name 标签的值必须相同,因为通过 servlet 标签中的 servlet-name
    标签映射到 servlet-class 标签中的值,最终访问 servlet-class 标签中的 class。

  • servlet和servlet-mapping都含有
    主要原因是想通过servlet-name作为纽带,将servlet-class和url-pattern构成联系,从而使URL映射到类servlet-class所指定的类中

Spring为什么要结合使用HandlerMapping以及HandlerAdapter来处理Handler?
主要原因是符合和面向对象中单一职责原则,代码架构清晰,便于维护,代码可复用性高。如HandlerAdapter可能会被用于处理多种Hander。
Spring mvc 请求处理_第3张图片

  1. 当DispatcherServlet接到请求时,他先回查找适当的处理程序来处理请求。DispatcherServlet通过一个或者多个处理程序映射,将每个请求映射到处理程序中。处理程序映射配置在web应用程序的上下文中,是实现了HandlerMapping接口的Bean。它负责为请求返回一个适当的处理程序(也就是Controller)。处理程序映射通常根据请求的URL将请求映射到处理程序(Controller)。
  2. 一旦DispatcherServlet选择了适当的控制器,它就会调用这个控制器来处理请求。
  3. 控制器处理完请求后,会将模型和视图名(有时候是视图对象)返回给DispatcherServlet。模型包含了控制器要传递给视图进行显示的属性。如果返回的是视图名称,它会被解析成视图对象再进行呈现。绑定模型和视图的基本类是ModelAndView.
  4. 当DispatcherServlet接收到模型和视图名称时,它会将逻辑视图名称解析成视图对象再进行呈现。DispatcherServlet从一个或者多个视图解析器中解析视图。视图解析器配置在Web应用程序上下文中,是实现了ViewResolver接口的Bean。它的任务是根据逻辑视图名称返回试图对象。
  5. 一旦DispatcherServlet将视图名称解析称为视图对象,它就会呈现视图对象,并传递控制器返回的模型。视图的任务是将模型属性展示给用户。

DispatcherServlet接收到请求后如何映射到Controller?
在Spring MVC中,web请求被Web应用程序上下文中声明的一个或者多个处理程序映射Bean映射到Controller,Spring MVC提供了几种HandlerMapping实现:
  BeanNameUrlHandlerMapping(默认情况),他根据Controller Bean名称中指定的URL模式将请求映射到处理程序上。
eg. …
当你访问http://******/welcome.htm这个URL时,DispatcherServlet通过BeanNameUrlHandlerMapping映射就找到了WelcomeController。
  ControllerClassNameHandlerMapping,它是按控制器类名称映射请求。
   SimpleUrlHandlerMapping,用定制的映射定义来映射请求。
Spring mvc 请求处理_第4张图片
Controller接口是Spring MVC中所有控制器类的基本接口。通过实现这个接口,你可以创建自己的控制器。在handleRequest()方法中,可以随意地处理Web请求。
AbstractController:如果你想让控制器具备一些基本的特性,如过滤受支持的HTTP方法(GET,POST和HEAD),以及在HTTP响应中生成cache-control头部等,你可以让它扩展AbstractController类。
ParameterizableViewController:用来创建带有参数化视图的控制器。
SimpleFormController:它支持命令对象的概念(commandName),并且可以将表单域的值绑定到命令对象的同名属性上。
AbstractWizardFormController:为向导表单的处理定义了基本的任务。向导表单有多个单页,因此必须为向导表单控制器定义多个页面视图。然后这个控制器可以跨越所有这些表单页面来管理表单状态。向导表单会有多个动作,不像SimpleFormController只有单个提交动作。AbstractWizardFormController会根据特殊的请求参数决定用户的动作,通常是用提交按钮的名称来指定动作的。
_finished: 完成向导表单。
_cancel: 取消向导表单。
_targetx: 进入目标页面,这里的x是从0开始的页面索引。
MultiActionController:允许你将多个相关的动作分组到一个控制器中。
常见的视图类型:
Spring mvc 请求处理_第5张图片

几种常见的ViewResolver的解析:
InternalResourceViewResolver: 根据URL解析视图。通过添加前缀和后缀的方法,将每个视图名称都映射到一个URL上。
XmlViewResolver: 从XML配置文件中解析视图。将视图声明成Spring的Bean,并按他们的Bean Name进行解析。
ResourceBundleViewResolver: 从ResourceBundle中解析视图。
用多个视图解析器解析视图, 需要注意的是,您需要为你配置的视图解析器配置解析的优先级。 value越小,优先级越高。

你可能感兴趣的:(spring-mvc,spring,mvc)