文章目录
概述
Spring Boot应用通过依赖spring-boot-starter-web包,使我们能够快速构建web应用。模块默认引入了jackson、嵌入tomcat、spring-web和spring-webmvc。
原理
有三种方式实现webmvc配置
- 自动配置,项目通过引入了对应jar包,使的classpath路径下存在对应类,spring boot应用启动时通过扫描/META-INF/spring.factories文件中的WebMvcAutoConfiguration,完成web模块的引入。实现WebMvcConfigurer接口可增加自定义配置。
- 通过使用@EnableWebMvc注解和实现WebMvcConfigurer接口,完成自定义mvc配置
- 通过继承WebMvcConfigurationSupport类
自动配置
WebMvcAutoConfiguration
注解的含义
当application类型为servlet,classpath中存在Servlet、DispatcherServlet、WebMvcConfigurer类且不存在WebMvcConfigurationSupport类才装载该类到IOC容器中
在DispatcherServletAutoConfiguration、TaskExecutionAutoConfiguration和ValidationAutoConfiguration类引入之后导入
在WebMvcAutoConfiguration配置类中定义的内容如下
当HiddenHttpMethodFilter和FormContentFilter类不存在时且配置中存在spring.mvc.formcontent.filter为true,引入默认的OrderedHiddenHttpMethodFilter和OrderedFormContentFilter类
引入配置类WebMvcAutoConfigurationAdapter和EnableWebMvcConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
····
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer{
}
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware{
}
····
}
EnableWebMvcConfiguration
实现WebMvc默认配置,继承DelegatingWebMvcConfiguration类,通过@AutoWired注解加载beanFactory中的WebMvcConfigurer类型到WebMvcConfigurerComposite中
通过调用持有的WebMvcConfigurer中的方法,将对应mvc拓展设置注册到对应的mvc组件中,如调用WebMvcConfigurer的addInterceptors将拦截器注册到处理器映射器
注册默认RequestMappingHandlerAdapter、RequestMappingHandlerMapping到IOC容器
注册WelcomePageHandlerMapping到IOC容器,首页处理器映射器,默认为index,从资源路径中查询index.html文件
FormattingConversionService格式转换器
Validator验证器
ContentNegotiationManager内容协商管理,用于判断一个请求的媒体类型
WebMvcAutoConfigurationAdapter
注解内容:导入EnableWebMvcConfiguration类,启用WebMvcProperties(spring.mvc前缀)和ResourceProperties(spring.resources前缀)配置属性
InternalResourceViewResolver、BeanNameViewResolver注册视图解析器
ContentNegotiatingViewResolver内容协商解析器
LocaleResolver国际化解析
RequestContextFilter请求内容过滤器,将请求内容暴露给当前线程
在WebMvcAutoConfiguration中我们看到了注解@AutoConfigureAfter,表明DispatcherServletAutoConfiguration类会先于被解析
DispatcherServletAutoConfiguration
注解
当application类型为SERVLET且classpath中包含DispatcherServlet类时才加载
在ServletWebServerFactoryAutoConfiguration之后加载
内容
加载DispatcherServletConfiguration(初始dispatcherServlet和mutilpartResolver)和DispatcherServletRegistrationConfiguration配置类
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
// classpath中存在ServletRegistration类且beanFactory中不存在dispatcherServlet类才加载
protected static class DispatcherServletConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
// 当beanFactory中存在MultipartResolver类且不存在名为multipartResolver的bean
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
}
}
在初始dispatcherServlet之前会先加载ServletWebServerFactoryAutoConfiguration配置类
ServletWebServerFactoryAutoConfiguration
注解内容:当application类型为SERVLET且存在ServletRequest类才加载
ServerProperties配置类定义了启动端口、最大http头等信息(前缀server.port)
通过BeanPostProcessorsRegistrar注入完成对WebServerFactoryCustomizerBeanPostProcessor和ErrorPageRegistrarBeanPostProcessor类注入
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
// ServletWebServerFactory自定义器,通过传入serverProperties来定义ConfigurableServletWebServerFactory属性
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
// 存在tomcat类时加载
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
}
@EnableWebMvc+WebMvcConfigurer
类继承图
在WebMvcAutoConfiguration的注解中存在@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),说明如果BeanFactory中存在WebMvcConfigurationSupport对象则不自动进行mvc配置
@EnableWebMvc
导入了DelegatingWebMvcConfiguration类,其中自动装填了setConfigurers(List configurers)方法
DelegatingWebMvcConfiguration继承WebMvcConfigurationSupport类实现了RequestMappingHandlerMapping、HandlerExceptionResolver、ViewResolver及HttpRequestHandlerAdapter类的bean注册
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
WebMvcConfigurer
配置webMvc
public interface WebMvcConfigurer {
// 帮助配置HandlerMappings路径匹配选项,例如尾部斜杠匹配、后缀注册、路径匹配器。
// suffixPatternMatch默认true /hello -> 匹配 /hello.*
// trailingSlashMatch默认true /hello -> 匹配 /hello/
default void configurePathMatch(PathMatchConfigurer configurer) {
}
// 添加拦截器
default void addInterceptors(InterceptorRegistry registry) {
}
// 跨域请求处理
default void addCorsMappings(CorsRegistry registry) {
}
// 添加uri对应视图转换
default void addViewControllers(ViewControllerRegistry registry) {
}
// 添加处理程序以服务于静态资源,自定义静态资源映射目录
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
}
WebMvcConfigurationSupport
通过实现该类完成mvc的配置,存在该类则spring boot自动配置不生效,在静态块中判断是否存在json转换器
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
@Nullable
private ApplicationContext applicationContext;
@Nullable
private ServletContext servletContext;
@Nullable
private List<Object> interceptors;
}