6.1 Spring MVC的核心分发器DispatcherServlet
6.1.1 核心分发器DispatcherServlet介绍
在未使用Spring Boot开发Web应用时,如果想要使Spring MVC生效,则需要增加Spring MVC相关的配置文件,并且在web.xml中配置DispatcherServlet以及对它的servlet-mapping节点进行请求地址的映射,配置内容如下所示:
在项目开发完成后启动Servlet容器,比如Tomcat服务器或者Jetty服务器装载DispatcherServlet,就可以进行基于Spring MVC的Web项目开发及测试了。
DispatcherServlet是Spring MVC核心的前端控制器,负责接收用户的请求,并根据用户的请求返回相应的视图给用户,其执行流程如图6-1所示。
图6-1 DispatcherServlet执行流程
首先,用户发起请求,请求到达前端控制器DispatcherServlet,前端控制器再根据用户的URL请求调用处理器映射器查找匹配该URL的Handler,并返回一个执行链。然后,处理器适配器调用相应的Handler进行业务处理并返回给前端控制器一个ModelAndView对象。前端控制器再请求视图解析器对返回的逻辑视图进行解析。最后前端控制器将返回的视图进行渲染,并把数据封装到Request域中返回给用户。
6.1.2 DispatcherServlet自动配置的日志输出
在第4章中笔者创建了第一个Spring Boot项目。在初始化时选择了其中的Web模块,即在pom文件中引入了spring-boot-starter-web。该模块包含了Spring MVC相关依赖,开发了第一个Web功能,即在控制器类中实现了一个简单的字符串返回方法,并对该方法进行了请求地址映射设置,没有再做其他配置操作。该项目启动后就能够进行正常的Web请求并正确返回数据。
结合DispatcherServlet的原理和工作流程可知,Spring Boot项目在启动后,Spring MVC的核心分发器DispatcherServlet正常配置并装载,才使得/hello请求能够正常返回数据。
但是,在使用Spring Boot开发Web项目时,开发人员只导入了spring-boot-starter-web场景启动器,根本未进行任何配置, DispatcherServlet就可以正常加载并使用。这是怎么一回事呢?DispatcherServlet是如何被装载到Servlet容器中的呢?Spring Boot究竟做了哪些配置,让Spring MVC的相关配置都注入IOC容器中并生效,从而使得开发人员可以零配置进行Web开发呢?
在Spring Boot 2.1.0版本的项目启动之后,启动日志中包含一条记录:
如图6-2所示,Spring Boot项目在启动过程中DispatcherServlet就已经被装载并且映射到 [/]路径上了。
启动日志是通过ServletRegistrationBean类的addRegistration()方法打印出来的,源码如图6-3所示。
不过,在Spring Boot 2.1.1版本之后,“Servlet dispatcherServlet mapped to [/]”这行日志输出代码就被Spring官方开发人员删除了。本书所使用的项目源码的Spring Boot版本是2.3.7。在该版本的代码中也没有这行日志输出语句。2.3.7版本的addRegistration()方法源码如图6-4所示。
图6-2 Spring Boot 2.1.0版本项目的启动日志
图6-3 Spring Boot 2.1.0版本的addRegistration()方法源码
图6-4 Spring Boot 2.3.7版本的addRegistration()方法源码
虽然没有了这行日志,但是对于DispatchServlet的注册和自动配置没有影响。流程和源码并没有太多改动。接下来笔者就根据这行消失的日志代码来回答前文提出的疑问。
笔者将结合源码来介绍Spring MVC的核心分发器DispatcherServlet在Spring Boot项目中自动配置的知识,让读者明白Spring Boot针对DispatcherServlet做了哪些自动配置以及如何使这些配置生效的。