Spring MVC 的基本概念,组件和核心逻辑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/83089639

基本概念

前端控制器Servlet

DispatcherServletSpring MVC 的前端控制器Servlet,也就是所有到达请求的统一处理入口,具体处理工作派发给其他Spring MVC组件实际完成。执行请求处理的其他Spring MVC 组件被定义为特定类型的 bean。这些组件bean按照Spring MVC定义好的的工作模式和流程(build-in contracts)协同工作。

handler mapping

handler mapping 机制负责请求(request)/URL和请求处理者handler之间的映射关系。这种关系通常通过配置指定,可能是通过xml配置文件指定,也可以使用注解方式@Controller+@RequestMapping指定。

handler mapping机制中有一个接口HandlerMapping,每个HandlerMapping实例的核心内容是一组URL pattern跟对应的handler的映射表。

Spring Web应用程序启动时,严格来讲,是 DispatcherServlet 初始化过程中,会搜集各种配置信息初始化创建HandlerMapping实例。

一个Spring Web应用会有不止一个 HandlerMapping 实例,并且这些HandlerMapping可以排序,每个HandlerMapping 实例也可以包含多个<URL pattern,Handler>映射对。 当一个请求到达时,Spring MVC 会根据排好的顺序查找第一个匹配请求URLHandlerMapping 并结合所设置的pre/post inteceptors构造一个 HandlerExecutionChain 对象用于处理该请求。

handlerhandler adpater

Spring MVC 对一个请求的真正处理者。DispatcherServlet接收到一个请求后最终会定位到一个handler使用这个handler处理该请求。

DispatcherServlet并不直接使用handler处理请求,而是通过一个叫做 handler adpater的中间层。每种handler都有对应支持它的handler adpater,handler adpaterDispatcherServlet屏蔽了handler处理请求的所有细节。你也可以理解成DispatcherServlet只认识handler adpater,并不认识handler

handler adpater 对应的接口是HandlerAdapter

handler interceptor

一个 handler interceptor 用于在一个 handler 调用的 前/后 或者请求处理完成时提供特定的逻辑。对应接口是HandlerInterceptor

handler execution chain

一个handler execution chain是一个handler加上一组handle interceptors。对应接口HandlerExecutionChain

controller

一般意义上的控制器,认为是类还是方法都不是大问题。举例来讲,它一般是开发人员使用注解@Controller定义的那个类,可以称之为conroller class/类,该类的每个使用@RequestMapping注解的public方法,是一个个controller method/方法,用于处理符合某个URL模式的请求。

理论上来讲,一个Web应用中所有的controller method/方法都放到一个controller class/类中没有问题。但通常开发人员会根据controller method/方法在业务上的亲密关系将它们实现到不同的controller class/类

无论是 controller, controller class/类,controller method/方法 都可以理解为 MVC中的C

controller method/方法 的实现逻辑由开发人员提供,当controller method/方法 基于模板技术提供一个页面时,它的流程一般是 :

  1. 接收和检查参数: 来自 request parameter, header, cookie 等;
  2. 根据参数调用服务层逻辑,这里会修改服务端数据的状态,从服务端获取一些数据放到model
  3. 返回目标视图的名称logical view name(一个字符串);

controller method/方法在上述流程结束返回到调用方DispatcherServlet后,DispatcherServlet会根据返回的modellogical view name找到相应的viewResolver,将model数据结合相应的view模板文件生成最终写入响应(response)的数据。

controller method/方法所处理的model和所指定的logical view name通常通过一个数据结构ModelAndView来组织。

概念model对应类org.springframework.ui.ModelMap/接口org.springframework.ui.Model

controller method/方法 直接输出响应数据时,比如处理的AJAX请求Restful API,它的流程主要是:

  1. 接收和检查参数: 来自 request parameter, header, cookie 等;
  2. 根据参数调用服务层逻辑,这里会修改服务端数据的状态,构建将要写入响应的数据对象;
  3. 将响应数据对象写入到响应(有两种方式);
    • controller method/方法上使用@ResponseBody注解,方法直接返回响应数据对象;
    • controller method/方法内直接打开响应的输出流,将响应数据对象写入响应。

这里这两种常用的方式都可以达到目标,但一般建议使用@ResponseBody注解的方式,这样通过配置即可指定响应数据对象自动被转换成JSON 还是 XML,同时还能方便地设置字符集。而在controller method/方法内直接打开响应的输出流写入相应数据的方式需要开发人员自己关注这些细节。

model

可以理解成 MVC中的 M,实际上是类Map的一种数据结构,该数据结构贯穿于整个controller method/方法的调用,controller method/方法可以向其中添加更多的数据,然后将该数据结构交给view以形成最终返回给客户端的响应数据。

parameters

狭义来说可以认为是request.getParameters()中的那些参数,广义来说可以是来自请求的任何数据,比如request.getParameters()的那些参数(可能来自HTML form,或者url queryString),请求的头部数据,请求携带的cookie中的数据,或者开发者在request body自定义的数据格式中分析出来的参数。

对于request.getParameters()的那些参数(可能来自HTML form,或者url queryString),请求的头部数据,请求携带的cookie中的数据,Spring MVC都有相应的注解直接获取这些信息。

view

对应的接口是org.springframework.web.servlet.View。对于基于模板的视图技术而言,不同的模板引擎有不同的View实现类,比如使用FreeMarker时,是类org.springframework.web.servlet.view.freemarker.FreeMarkerView。调用者根据controller method/方法指定的logical view name创建该View实例,对应到模板引擎相应的模板文件,然后调用该View的渲染方法render(model,request,response),将模板文件内容中的占位符或者变量替换成最终要展示的数据,然后写入数据到响应response

logical view name

view的名称字符串,一般是相对路径加上视图模板文件的文件名(不含文件扩展名部分)。

view resolver

用于处理特定类型视图的视图解析器,比如 FreeMarker, Velocity, 等模板引擎的视图解析器或者JSP视图解析器,一个Web应用可以配置多个视图解析器。这些配置的视图解析器会在DispatcherServlet初始化时被加载供请求处理是使用。

viewview resolver都可以理解成MVC中的V部分。

redirecting to view

//TODO

redirect

//TODO

forward

//TODO

locale

//TODO

theme

//TODO

flash attributes

//TODO

基本组件

组件类型 说明
HandlerMapping 请求和handler以及一组前置/后置处理器(handler interceptors)之间的映射。
HandlerAdapter 辅助DispatcherServlet调用某个handler的适配器,主要目的是屏蔽handler调用细节。
比如,调用一个带有注解的控制器方法通常需要理解各种注解,而HandlerAdapter就会封装处理这些细节。
HandlerExceptionResolver 将异常映射到View的解析器,也允许更复杂的异常处理代码逻辑。
ViewResolver 解析逻辑view名称到真正的View
LocaleResolver & LocaleContextResolver 本地化解析器,基于本地化设置和时区配置,主要用于提供国际化视图。
ThemeResolver 主题解析器,解析Web应用所使用的主题,比如不同的应用针对不同界面提供个性化的布局,配色等等。
MultipartResolver multi-part请求处理,主要用于处理基于HTML表单的文件上传。
FlashMapManager 保存/提取跨请求的FlashMap属性传递,通常伴随redirect

HandlerMapping

HandlerMapping有多个实现类 :

介绍
BeanNameUrlHandlerMapping 映射URL到bean,例子:对于这种映射方式,/foo 由 bean foo 处理。
DispatcherServlet的缺省工作模式,配合 DefaultAnnotationHandlerMapping 一起使用。
SimpleUrlHandlerMapping 允许自定义映射关系。
SimpleUrlHandlerMapping 支持直接的URL到bean实例/名称的映射,支持URL通配符到bean实例/名称的映射
RequestMappingHandlerMapping 处理@Controller类中所有注解@RequestMapping定义的请求/handler映射

HandlerMapping的实现类都继承自AbstractHandlerMapping,所以他们有以下共同的属性,可以通过这些属性定制一个HandlerMapping

属性 介绍
interceptors 通常符合某个格式的URL请求会被映射到某个handler和一组interceptors,该属性就记录了这组要应用的interceptors
defaultHandler 如果当前HandlerMapping没有找到匹配的handler时所要使用的handler
order 决定使用哪个handler是基于一定的顺序的,该属性定义顺序
alwaysUseFullPath true:使用在当前Servlet上下文(context)的全路径查找目标handler,false:使用仅在当前Servlet映射(mapping)中路径查找目标handler。
例子:
当前 Servlet 映射到 /testing/*,alwaysUseFullPathtrue时使用/testing/viewPage.html,而如果alwaysUseFullPathfalse,使用/viewPage.html

拦截器 HandlerInterceptor

Spring MVC 的HandlerMapping机制包含了HandlerInterceptor的概念,如果你想对符合某些特征的请求应用一些特定的功能,就可以使用HandlerInterceptor。比如你想要求某些URL被访问时用于必须已经登录,你就可以实现一个检查用户是否已经登录的HandlerInterceptor

HandlerInterceptor是一个接口,该接口定义了三个方法:

  • preHandle() – 真正的 handler 执行之前被调用
  • postHandle() – 真正的 handler 执行之后被调用
  • afterCompletion() – 整个request被处理完成时调用
    这三个方法提供了足够的灵活性用于进行各种预处理和后置处理。

handler/interceptor 的关系可以跟 servlet/filter 的关系做类比更容易理解。

Handler

介绍
ResourceHttpRequestHandler 对静态资源文件的支持,
静态资源文件路径也可以是classpath路径,比如classpath:/META-INF/resources/webjars/
HandlerMethod 对一个handler方法的封装,
比如@Controller类中@RequestMapping注解的每个方法会被封装成一个HandlerMethod

HandlerAdaptor

当通过 HandleMapping机制获得包含handlerHandlerExecutionChain实例后,DispatcherServlet并不是直接调用其中的handler,而是通过了一个间接层:适配器HandlerAdaptor。该适配器接口使DispatcherServlet变得可以被无限扩展。DispatcherServlet通过该接口访问实际的handler,这样的话DispatcherServlet就不用知道各种handler的具体逻
辑,细节被屏蔽了。当然,每种handler都必须有配套支持的HandlerAdaptor实现。

介绍
RequestMappingHandlerAdapter 支持类型为org.springframework.web.method.HandlerMethod的handler
HttpRequestHandlerAdapter 支持类型为org.springframework.web.HttpRequestHandler的handler
SimpleControllerHandlerAdapter 支持类型为org.springframework.web.servlet.mvc.Controller的handler

HandlerAdaptor接口不是面向应用开发人员的,它面向开发自己的web工作流的开发人员。

Spring MVC的典型处理流程

来自官网 Figure 22.1. The request processing workflow in Spring Web MVC (high level)

参考资料

官方文档 Spring Web MVC framework - v4.3.9
缺省配置Spring boot Web中一个请求的处理流程

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/83089639