Spring Boot Web Mvc 自动装配

SpringWebMvc 自动装配大纲:

img

在引入 spring-boot-starter-web 的依赖后,SpringBoot 会自动进行Web环境的装载。

借由上一篇我们总结的规律,那么 SpringWebMvc 的自动配置就应该叫:WebMvcAutoConfiguration

1. WebMvcAutoConfiguration

在配置中标注了,WebMvcAutoConfiguration 必须在 DispatcherServletAutoConfigurationTaskExecutionAutoConfigurationValidationAutoConfiguration 执行完后再执行。故要先看他们都干了什么。

2. DispatcherServletAutoConfiguration

文档注释原文翻译:

Auto-configuration for the Spring DispatcherServlet. Should work for a standalone application where an embedded web server is already present and also for a deployable application using SpringBootServletInitializer.

DispatcherServlet 的自动配置。它起作用应该依赖于一个已经存在嵌入式Web服务器的独立应用程序,也适用于使用 SpringBootServletInitializer 的可部署应用程序。

其中 SpringBootServletInitializer 是SpringBoot用于打war包时留给Web容器初始化应用的钩子。

至于它的作用,咱们暂且放在一边,留在WebMvc部分详细来看。

DispatcherServletAutoConfiguration 的源码中又标注了 @AutoConfigureAfter ,说明它又要在 ServletWebServerFactoryAutoConfiguration 之后再执行。

3. ServletWebServerFactoryAutoConfiguration

这个类又导入了几个组件:EmbeddedTomcatEmbeddedJettyEmbeddedUndertowBeanPostProcessorsRegistrar

3.1 EmbeddedTomcat

由条件装配的注解 @ConditionalOnClass 可以看到,当前 classpath 下必须有 Tomcat 这个类,该配置类才会生效。对比 Jetty:

默认导入的 spring-boot-starter-web 中导入的是 Tomcat 的依赖,故 Jetty 不会生效。

3.2 ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar

它实现了 ImportBeanDefinitionRegistrar 接口,在registerBeanDefinitions中可以编程式向IOC容器中注入组件。它注册的两个组件是:WebServerFactoryCustomizerBeanPostProcessorErrorPageRegistrarBeanPostProcessor

3.2.1 WebServerFactoryCustomizerBeanPostProcessor

文档注释原文翻译:

BeanPostProcessor that applies all WebServerFactoryCustomizer beans from the bean factory to WebServerFactory beans.

Bean的后置处理器,它将 Bean 工厂中的所有 WebServerFactoryCustomizer 类型的 Bean 应用于 WebServerFactory 类型的 Bean。

可以看出它的作用是执行组件定制器的,定制器下面会有介绍。

3.2.2 ErrorPageRegistrarBeanPostProcessor

文档注释原文翻译:

BeanPostProcessor that applies all ErrorPageRegistrars from the bean factory to ErrorPageRegistry beans.

Bean的后置处理器,它将Bean工厂中的所有 ErrorPageRegistrars 应用于 ErrorPageRegistry 类型的Bean。

可推测出它的作用是将所有设置的错误页跳转规则注册到错误处理器中。

附: ErrorPageRegistry 接口的源码:

3.3 SpringBoot中的Customizer

一般情况下,修改 SpringBoot 的配置,都是通过 application.yml 显式地声明配置。除此之外,还可以使用 Customizer 定制器机制。

在WebMvc模块中,使用 Customizer 修改配置,可以实现 WebServerFactoryCustomizer 接口。该接口可以传入泛型,泛型的类型是 ServletWebServerFactory

以下是举例:

Customizer 可以设置配置顺序(上面的 @Order 注解,或 Ordered 接口),通过配置执行顺序,可以自定义的覆盖某些自动配置,达到个性化配置的目的。

提这个 Customizer 机制,是为了看下面的配置类:

3.4 ServletWebServerFactoryAutoConfiguration中注册的其他组件

巧了,它就创建了两个定制器,并把 ServerProperties 传入,让定制器根据配置信息做自动化配置。

3.4.1 ServerProperties的来源

@ConfigurationProperties 的作用:可用于某个类上,设置属性profix用于指定在工程的全局配置文件(application.propertiesapplication.yml)中的配置的根信息。

简言之, @ConfigurationProperties 可以实现指定属性开头的属性值注入。

那么 ServerProperties 的属性值来源,就是全局配置文件中的server开头的所有配置。

以上执行完毕后,ServletWebServerFactoryAutoConfiguration 的全部配置也就完成了,下面执行 DispatcherServletAutoConfiguration

4. DispatcherServletAutoConfiguration

里面嵌套了两个内部类,分别注册 DispatcherServletDispatcherServletRegistrationBean

在继续阅读注册 DispatcherServlet 之前,先了解 SpringBoot 注册Servlet的机制。

4.1 SpringBoot注册传统Servlet三大组件

由于 SpringBoot 项目中没有 web.xml(Servlet3.0规范中就没有了),故有另外的方式注册Servlet三大组件。SpringBoot 提供两种方式。

4.1.1 组件扫描@ServletComponentScan

在启动类上标注 @ServletComponentScan 注解,指定 value/basePackage,即可扫描指定包及子包下所有的 Servlet 组件。

之后注册 ServletFilterListener 组件,就可以像 Servlet3.0 规范后的方式,直接在 Servlet 上标注 @WebServlet 等注解即可。

4.1.2 借助RegistrationBean

自定义的Servlet可以创建 ServletRegistrationBean<T extends Servlet>

使用时,只需要在配置类中注册一个 ServletRegistrationBean,创建它的对象时,使用有参构造方法,传入 Servlet 和 urlMapping 即可。

一个简单的例子:

4.2 注册DispatcherServlet

只关注核心部分源码:

DispatcherServletConfiguration 类上标注了 @EnableConfigurationProperties,代表启用指定类的 ConfigurationProperties 功能。

下面创建 DispatcherServlet,并将默认的一些配置设置到 DispatcherServlet 中。这些属性就来自于已经被启用的 HttpPropertiesWebMvcProperties 中。

至此,DispatcherServletAutoConfiguration 执行完毕,回到 WebMvcAutoConfiguration 中。

5. WebMvcAutoConfiguration

5.1 WebMvcConfiguration

在SpringBoot2.x中,自定义的WebMvc配置需要实现 WebMvcConfigurer 接口,并重写接口中需要配置的方法即可。

WebMvcAutoConfigurationAdapter 也实现了该接口,并进行默认配置。

5.1.1 配置HttpMessageConverter

5.1.2 ViewResolver的组件注册

注册了ViewResolverLocaleResolver

  • ContentNegotiatingViewResolver:最高级的 ViewResolver,负责将视图解析的工作代理给不同的 ViewResolver 来处理不同的View

  • BeanNameViewResolver:如果 Controller 中返回的视图名称恰好有一个Bean的名称与之相同,则会交予Bean处理

  • InternalResourceViewResolver:最常用的 ViewResolver,通过设置前后缀来匹配视图

5.1.3 静态资源映射

注册静态资源路径。可以看到,它将 /webjars 路径下的资源都映射到 classpath:/META-INF/resources/webjars 中。

webjars 可以将前端的框架变成Maven依赖,减少手动加入静态资源的工作。

除了注册 webjars 的资源路径,倒数第二行,还取到 resourceProperties 中的 staticLocations,也加入进去。

ResourceProperties 中的 staticLocations:

这也解释了为什么静态资源文件放在 resources 中和放在 static 中都能被正常加载的原因。

5.1.4 主页的设置

由此可以看出,欢迎页面/主页的设置,是取的静态资源路径中的 **index.html** 文件

5.1.5 应用图标的设置

可以明显的看到默认的图标名称是 favicon.ico,且放在静态路径下的任意位置都可以被扫描到。

5.2 EnableWebMvcConfiguration

5.2.1 注册的核心组件

SpringWebMvc 中最核心的两个组件:处理器适配器、处理器映射器。

注册了 Hibernate-Validator 参数校验器。

注册了全局异常处理器。

小结

  1. 自动配置类是有执行顺序的, WebMvcAutoConfiguration 的执行顺序在 ServletWebServerFactoryAutoConfigurationDispatcherServletAutoConfiguration 之后。

  2. SpringBoot会根据当前classpath下的类来决定装配哪些组件,启动哪种类型的Web容器。

  3. WebMvc的配置包括消息转换器、视图解析器、处理器映射器、处理器适配器、静态资源映射配置、主页设置、应用图标设置等。

  4. 配置 SpringBoot 应用除了可以使用 properties、yml 之外,还可以使用 Customizer 来编程式配置。

最后更新于

这有帮助吗?