前言

Spring MVC是工作在Java Servlet之上的一套MVC框架,本文将通过分析Spring MVC的请求处理流程来学习Spring MVC的工作原理。

主要将分析:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
  • DispatcherServlet MVC门面组件,请求入口,响应出口。
  • HandlerMapping MVC组件,映射请求为处理器。
  • HandlerAdapter MVC组件,调用控制器。解耦控制器,保证灵活性。
  • HandlerExceptionResolver MVC重要组件,处理查找和执行处理器期间抛出的所有异常。
  • ViewResolver MVC组件,返回视图。

版本:Spring Framework 4.x

1.DispatcherServlet

DispatcherServlet是HTTP请求处理程序的中央调度器,调度注册的处理程序来处理Web请求。它主要包括以下组件:

  • HandlerMapping 处理器映射,负责路由请求。可以多个,存在先后顺序。
  • HandlerAdapter 处理器适配器,使用适配器模式,用于自定义工作流。可以多个,存在先后顺序。
  • HandlerExceptionResolver 处理器异常解析器,处理异常。可以多个,存在先后顺序。
  • ViewResolver 视图解析器,用于将视图名解析为View对象。可以多个,存在先后顺序。
  • RequestToViewNameTranslator 当处理器没有返回View或视图名称时,将请求转换为视图名。
  • MultipartResolver 多部分文件解析器,用于文件上传解析。默认不提供。
  • LocaleResolver 地区解析器。

组件的注册

支持多个组件的组件类型,将从上下文中获取该类型的所有实例。对于单个组件类型,根据bean名称获取实例。对于默认组件,如果上下文未存在该组件,将使用默认配置。

请求的处理流程

首先遍历询问HandlerMapping列表查找匹配的处理器,返回一个HandlerExecutionChainHandlerExecutionChain包含了HandlerInterceptor列表,并封装了处理器对象。

然后遍历询问HandlerAdapter列表查找匹配的适配器。由HandlerAdapter执行处理器的处理逻辑,并返回一个ModelAndView

如果这个过程中发生了任何异常,将处理异常。

最后是渲染ModelAndView,返回响应。
Spring MVC 请求处理流程分析 随笔 第1张

2.HandlerMapping

处理器映射是将请求映射到处理器的工具抽象。

其接口方法如下:

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

方法返回值为HandlerExecutionChain,封装了HandlerInterceptor列表和处理器对象。

HandlerInterceptor

MVC框架级别的Filter,包含了三个拦截方法:

boolean preHandle(..) — 在实际的处理器执行前调用
void postHandle(..) — 在处理器执行后调用
void afterCompletion(..) — 在请求处理结束后调用

查找处理器逻辑

AbstractHandlerMapping是HandlerMapping的基本抽象类,所有的HandlerMapping实现类都继承于该类。其定义了查找Handler的模板方法:
Spring MVC 请求处理流程分析 随笔 第2张

3.HandlerAdapter

Spring MVC并没有限定Handler的具体类型或接口,而是支持Object类型,并由HandlerAdapter来完成处理器的调用,极大提升了Spring MVC的灵活性。
它主要定义了两个方法:

boolean supports(Object handler);//返回是否支持该处理器
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;//通过自定义工作流执行处理器,并返回MV

每一个HandlerMapping的实现,都对应着一个HandlerAdapter实现,只有该HandlerAdapter才知道如何调用确切的处理器。

基于注解驱动的HandlerMapping和HandlerAdapter

对基于注解的@Controller,@RequestMapping提供支持的是RequestMappingHandlerMappingRequestMappingHandlerAdapter。这里简单介绍一下它们的工作原理。

RequestMappingHandlerMapping

RequestMappingHandlerMapping在初始化时遍历上下文所有bean,如果其是一个控制器(声明了@Controller@RequestMapping)就扫描其所有方法。如果方法是一个处理器方法(声明了@RequestMapping)就将控制器、方法、映射信息注册到相关表中。

每次请求查找匹配的处理器,RequestMappingHandlerMapping就会查找其表,根据请求路径和其他参数返回匹配的HandlerMethod

RequestMappingHandlerAdapter

HandlerMethod类型的处理器提供了支持。

4.HandlerExceptionResolver

HandlerExceptionResolver处理查找和执行处理器阶段抛出的所有异常。

它的接口方法如下:

ModelAndView resolveException(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

一个HandlerExceptionResolver的处理方式是:

  • 返回一个ModelAndView,指向确切的错误视图
  • 返回一个空的ModelAndView,表示已经处理。
  • 返回null,交给链的下一个进行处理。

多个处理器异常解析器会依次调用,直到其中一个处理完成。

5.ViewResolver

传统Web的MVC架构,处理器最终返回一个视图名,而视图解析器负责这个工作。
其接口定义为:

View resolveViewName(String viewName, Locale locale) throws Exception;

在DispatcherServlet中的工作方式

在DispatcherServlet中,ViewResolver在渲染阶段进行工作:

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    //...
      view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
      if (view == null) {
         throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
               "' in servlet with name '" + getServletName() + "'");
      }
     //...
}

多个视图解析器以链的方式调用,直到其中一个返回一个View

View

View是视图的抽象,其完成最后的内容输出功能:

void render(Map<String, ?> model, HttpServletRequest 
request, HttpServletResponse response) throws Exception;

总结

本文从原理上大致分析了Spring MVC的基本工作原理,通过跟踪请求的处理流程来实现了。你可以自行阅读DispatcherServlet的源码,并一步步DEBUG来学习。

在理解这个过程时,切忌过于关注底层实现细节,而应该从抽象层面来理解。

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄