SpringBoot的Web自动配置和默认功能、WebMvcAutoConfiguration原理

目录

  • 1. 自动配置
  • 2. 提供的默认功能
  • 3. WebMvcAutoConfiguration原理
    • 3.1 生效条件
    • 3.2 效果
    • 3.3 WebMvcConfigurer接口
    • 3.4 为什么容器中放一个WebMvcConfigurer就能配置底层行为

SpringBoot的Web开发能力,由SpringMVC提供

1. 自动配置

查看org.springframework.boot:spring-boot-autoconfigure:3.1.1\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports,可以看到web相关的自动配置类如下:

org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

这些类通过配置类xxxProperties.class,绑定了配置文件的一些配置项

  1. SpringMVC的所有配置spring.mvc
  2. Web场景通用配置spring.web
  3. 文件上传配置spring.servlet.multipart
  4. 服务器的配置server。比如编码方式

2. 提供的默认功能

  1. 包含了ContentNegotiatingViewResolver和BeanNameViewResolver组件,方便视图解析
  2. 默认的静态资源处理机制: 静态资源放在static文件夹下即可直接访问
  3. 自动注册了Converter、GenericConverter、Formatter组件,适配常见数据类型转换和格式化需求。如配置文件自定义的日期属性,转换再格式化为java Bean的日期属性
  4. 支持HttpMessageConverters,可以方便返回json等数据类型,将java Bean直接返回成json数据
  5. 注册MessageCodesResolver,方便国际化及错误消息处理
  6. 支持静态index.html
  7. 自动使用ConfigurableWebBindingInitializer,实现消息处理、数据绑定、类型转化、数据校验等功能。即前端传过来的参数,转换成java Bean

注意:

  • 如果想保持springboot mvc的默认配置,并且自定义更多的mvc配置,如:interceptors、formatters、view controllers等。可以添加@Configuration注解到一个类上,再让这个类继承WebMvcConfigurer接口,并不要标注@EnableWebMvc
  • 如果想保持springboot mvc的默认配置,但要自定义核心组件实例,比如:RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver,给容器中放一个WebMvcRegistrations组件即可
  • 如果想全面接管Spring MVC,可以添加@Configuration注解到一个类上,再让这个类继承WebMvcConfigurer接口,并不要标注@EnableWebMvc
方式 用法 效果
全自动 直接编写控制器逻辑 全部使用自动配置默认效果
手自一体 @Configuration + 配置WebMvcConfigurer + 配置WebMvcRegistrations。不要标注@EnableWebMvc 保留自动配置效果,手动设置部分功能,定义MVC底层组件
全手动 @Configuration + 配置WebMvcConfigurer。标注@EnableWebMvc 禁用自动配置效果,全手动设置

3. WebMvcAutoConfiguration原理

3.1 生效条件

@AutoConfiguration(
    after = {DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}
)  // 在这些自动配置之后。其中TaskExecutionAutoConfiguration是做异步任务的,ValidationAutoConfiguration是做数据校验的
@ConditionalOnWebApplication(
    type = Type.SERVLET
)    // 如果是web应用,且类型是SERVLET就生效,REACTIVE响应式web不生效
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})  // 容器中没有这个Bean,才生效。默认就是没有
@AutoConfigureOrder(-2147483638)  // 自动配置优先级
@ImportRuntimeHints({WebResourcesRuntimeHints.class})    // 导入运行时的指标统计

3.2 效果

  1. 放了两个Filter:
    1. HiddenHttpMethodFilter;页面表单提交Rest请求。表单默认只能提交GET、POST请求,有了这个Filter就能提交PUT、DELETE请求了
      b. FormContentFilter: 表单内容Filter,配合HiddenHttpMethodFilter使用。默认GET(数据放URL后面)、POST(数据放请求体)请求可以携带数据,PUT、DELETE的请求体数据会被忽略,加了这个Filter后PUT和DELETE就能携带数据了
  2. 给容器中放了WebMvcConfigurer组件。具体如下:
    @Configuration(
        proxyBeanMethods = false
    )
    @Import({EnableWebMvcConfiguration.class})    // 额外导入了其他配置
    @EnableConfigurationProperties({WebMvcProperties.class, WebProperties.class})
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
    ......省略部分......
    }

所有的功能最终会和配置文件进行绑定。WebMvcProperties绑定了spring.mvc开头的配置,WebProperties绑定了spring.web开头的配置

3.3 WebMvcConfigurer接口

其中WebMvcConfigurer给SpringMVC添加各种定制功能,配置了SpringMVC底层的所有组件入口。如下所示:

// 路径匹配。如对RestMapping("/hello/**")进行匹配
default void configurePathMatch(PathMatchConfigurer configurer)
// 内容协商
default void configureContentNegotiation(ContentNegotiationConfigurer configurer)
// 异步支持
default void configureAsyncSupport(AsyncSupportConfigurer configurer)
// 默认处理:默认接收: /。静态资源和动态资源都由SpringMVC来处理
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
// 格式化器。如日期格式化
default void addFormatters(FormatterRegistry registry)
// 请求拦截器
default void addInterceptors(InterceptorRegistry registry)
// 添加资源处理器:处理静态资源规则。比如指定图片、css、js的路径(根路径、classpath、其它)
default void addResourceHandlers(ResourceHandlerRegistry registry)
// 前后端跨域规则
default void addCorsMappings(CorsRegistry registry)
// 视图控制器:/a直接跳转到xxx.html页面
default void addViewControllers(ViewControllerRegistry registry)
// 视图解析
default void configureViewResolvers(ViewResolverRegistry registry)
// Controller请求接收参数解析器
default void addArgumentResolvers(List resolvers)
// Controller请求返回值处理器
default void addReturnValueHandlers(List handlers)
// 消息转化器
default void configureMessageConverters(List> converters)
// 扩展:消息转换
default void extendMessageConverters(List> converters)
// 配置系统异常解析器
default void configureHandlerExceptionResolvers(List resolvers)
// 扩展:异常解析器
default void extendHandlerExceptionResolvers(List resolvers)
default Validator getValidator()
default MessageCodesResolver getMessageCodesResolver()

3.4 为什么容器中放一个WebMvcConfigurer就能配置底层行为

  1. WebMvcAutoConfiguration是一个自动配置类,它里面有一个EnableWebMvcConfiguration
  2. EnableWebMvcConfiguration继承于DelegatingWebMvcConfiguration,这两个都生效
  3. DelegatingWebMvcConfiguration利用DI把容器中所有WebMvcConfigurer注入进来
  4. 别人调用DelegatingWebMvcConfiguration的方法配置底层规则,而它调用所有WebMvcConfigurer的配置底层方法

你可能感兴趣的:(#,SpringBoot,spring,boot,自动配置,提供的默认功能,WebMvc自动配置原理,WebMvc配置接口)