前言
SpringMVC 请求处理相信大家都很熟悉了,本篇主要是基于 SpringMVC 处理请求的流程来阅读并调试源码,以及解决几个仅靠流程图无法解释的问题。
关于 Spring MVC 的流程思维导图分享给大家:
Spring 系列的学习笔记和面试题,包含 spring 面试题、spring cloud 面试题、spring boot 面试题、spring 教程笔记、spring boot 教程笔记、最新阿里巴巴开发手册(63 页 PDF 总结)、2020 年 Java 面试手册。一共整理了 1184 页 PDF 文档。
获取这份 1184 页 PDF 文档的 spring 全家桶资料。
本篇使用的 Spring 版本为 5.2.2.RELEASE
九大组件
SpringMVC 几乎所有的功能都由九大组件来完成,所以明白九大组件的作用,对于学习 SpringMVC 来说非常重要。
/** 文件上传解析器 /
private MultipartResolver multipartResolver;
/* 区域解析器,用于国际化 /
private LocaleResolver localeResolver;
/* 主题解析器 /
private ThemeResolver themeResolver;
/* Handler映射信息 /
private List handlerMappings;
/* Handler适配器*/
private List handlerAdapters;
/** Handler执行异常解析器 /
private List handlerExceptionResolvers;
/* 请求到视图的转换器 /
private RequestToViewNameTranslator viewNameTranslator;
/* SpringMVC允许重定向时携带参数,存在session中,用完就销毁,所以叫FlashMap /
private FlashMapManager flashMapManager;
/* 视图解析器 */
private List viewResolvers;
HandlerMapping:Handler 映射信息,根据请求携带的 url 信息查找处理器(Handler)。每个请求都需要对应的 Handler 处理。
HandlerAdapter:Handler 适配器,SpringMVC 没有直接调用处理器(Handler),而是通过 HandlerAdapter 来调用,主要是为了统一 Handler 的调用方式
ViewResolver:视图解析器,用来将字符串类型的视图名称解析为 View 类型的视图。ViewResolver 需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。
MultipartResolver:文件上传解析器,主要用来处理文件上传请求
HandlerExceptionResolver:Handler 执行异常解析器,用来对异常进行统一处理
RequestToViewNameTranslator:请求到视图的转换器
LocaleResolver:区域解析器,用于支持国际化
FlashMapManager:SpringMVC 允许重定向时携带参数,存在 session 中,用完就销毁,所以叫 FlashMap
ThemeResolver:主题解析器,用于支持不同的主题
九大组件中最重的的前三个,HandlerMapping、HandlerAdapter 和 ViewResolver,因为这是阅读源码时,避不开的三个组件。
我把 Spring MVC 相关的技术文章整理成了 PDF,老规矩,关注微信公众号 Java 后端 回复 666 下载。
调试准备
搭建一个基本的 Spring web 项目即可
Controller 部分
@Controllerpublic class IndexController
{
@RequestMapping(“/index/home”)
public String home(String id, Student student,
@RequestParam(“code”) String code)
{
System.out.println(student.getName());
return “index”;
}
@ResponseBody
@RequestMapping(“/index/list”)
public String list()
{
return “success”;
}
}
Entity 部分
public class Student { private String name; private Integer gender; // getter、setter}
还是那句话,Spring 源码非常庞大,不能只见树木不见森林,需要有针对性的阅读,所以本篇只需要关注主体流程即可。
核心方法
我们都知道,SpringMVC 有一个用来分发请求的前端控制器 DispatcherServlet,其中用来处理请求的方法就是 doService,该方法定义如下
doService
/** * Exposes the DispatcherServlet-specific request attributes and delegates to
{
@link
#doDispatch} * for the actual dispatching. */
@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception
{ logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include. Map
if (WebUtils.isIncludeRequest(request))
{
attributesSnapshot = new HashMap<>();
Enumeration> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements())
{
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX))
{
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make fra