今天梳理一下DispatcherServlet的组成结构,了解其各个核心功能。

DispatcherServlet只是一个普通的Servlet,它也会接收Java Web服务器的request和response参数,从request中获取请求信息,向response返回响应信息。

DispatcherServlet也是一个特殊的Servlet,为了适用日常Web应用开发,它需要兼容各种情况的业务流程:

如果是个文件上传请求,它需要对文件输入流进行处理,并及时清除临时文件。

它需要映射请求地址和对应的处理方法。

它需要将HTTP请求参数解析成对应Java对象。

它需要校验请求参数的合法性。

它需要将响应Java对象解析成对应格式的HTTP响应。

它需要对异常进行统一处理。

……

DispatcherServlet的类图如下:

每个成员变量集成了某种业务的功能,这些功能组合起来,能够支持绝大部分日常业务场景。

它还提供了多个扩展点,便于开发人员在业务流程中的某个节点进行扩展,增强Spring MVC功能以适应自己的系统。

MultipartResolver

MultipartResolver提供了文件上传业务的功能:

首先,它会对request参数进行校验,如果请求头Content-Type以multipart/开头,说明当前是文件上传请求。

如果是文件上传请求,DispatcherServlet会调用MultipartResolver成员变量,对文件请求进行处理。核心处理逻辑是,读取文件输入流,将文件临时保存到本地,然后将本地临时文件的信息封装成MultipartHttpServletRequest对象返回。开发人员在业务中读取到的实际上是本地临时文件,而不是网络中的文件二进制数据。

在业务处理完成后,DispatcherServlet还会调用MultipartResolver成员变量,及时将本地临时文件删除,避免资源浪费。

HandlerMapping

HandlerMapping提供了请求地址和对应处理方法的映射功能:

在项目启动时,HandlerMapping会对整个项目进行扫描,将开发人员定义的请求地址和处理方法一一对应,并且缓存起来。

当DispatcherServlet接收到请求时,会根据当前request的请求地址等信息,从HandlerMapping中获取对应的处理方法,便于后续调用。

DispatcherServlet持有HandlerMapping的列表,支持各种形式的请求地址-处理方法映射方式。例如@Controller就是最常使用的一种方式,对应的是RequestMappingHandlermapping。

HandlerMapping除了保存请求地址和处理方法映射关系,它还会存储拦截器HandlerInterceptor列表。

拦截器类似于Filter,会在处理方法前进行预处理,在处理方法后进行后处理,会在请求完成后进行最后处理,是Spring MVC提供的一个增强点。

例如,跨域资源共享(CORS)功能,就可以通过拦截器进行实现。

HandlerAdapter

HandlerAdapter是DispatcherServlet最核心的一个成员变量,它会实际调用开发人员定义的请求处理方法:

在项目启动时,HandlerAdapter会加载配置的参数解析器、返回值处理器、类型转换器等。

HandlerMapping和HandlerAdapter是一一对应的。当DispatcherServlet处理请求时,如果该请求地址-处理方法由某个HandlerMapping保存,会使用对应的HandlerAdapter进行处理。

HandlerAdapter会对request进行预处理,比如将请求参数解析成对应处理方法的形参对象,对请求参数进行规则校验。

HandlerAdapter会使用反射方式,传递解析后的参数进行调用处理方法。

HandlerAdapter会按照定义好的HTTP响应格式,将处理方法返回的Java对象解析成对应的数据格式进行响应。

DispatcherServlet持有HandlerAdapter的列表,与HandlerMapping列表一一对应。例如@Controller使用的RequestMappingHandlermapping,对应的是RequestMappingHandlerAdapter。

HandlerAdapter支持自定义参数解析器、返回值处理器、类型转换器等。例如@RequestBody、@RequestParam、@Validated和@ResponseBody等注解,都是通过这些解析器/处理器/转换器进行实现的。

HandlerExceptionResolver

HandlerExceptionResolver提供了全局异常处理的功能:

在项目启动时,HandlerExceptionResolver会扫描整个项目,加载异常处理的处理方法。

在DispatcherServlet处理请求过程中,包括MultipartResolver文件处理、HandlerMapping获取请求处理方法、拦截器的方法执行、HandlerAdapter执行请求处理方法过程,只要抛出了异常,都会最终交由HandlerExceptionResolver进行全局异常处理。

如果HandlerExceptionResolver不能处理该异常,或者在处理异常过程中抛出了新异常,都会直接将异常返回给Java Web服务器。

DispatcherServlet持有HandlerExceptionResolver的列表,支持各种形式的全局异常处理方式。例如@ControllerAdvice就是最常使用的一种方式,对应的是ExceptionHandlerExceptionResolver。

其他

以上介绍的是前后端分离模式下,所使用的核心功能。

DispatcherServlet还支持其他业务流程的支持,对应模块为:

LocaleResolver:国际化解析器。

ThemeResolver:主题解析器。

RequestToViewNameTranslator:请求-视图翻译器。

FlashMapManager:重定向管理器。

ViewResolver:视图解析器。

这些模块只在特殊场景才会使用,这里不做过多介绍。以后有机会可以对这些模块进行详细说明。

今日小结

本文对DispatcherServlet的核心功能进行了简单的梳理,但是详细总结了各个核心功能的处理流程。

自此我们对DispatcherServlet有了整体的概念,对后续深入学习有着重要的指导作用。

查看原文