一、SpringBoot自动配置MVC
1.1 ServletWebServerFactoryAutoConfiguration
@Configuration(proxyBeanMethods = false)
//在自动配置中具有最高优先级执行
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
//导致web注册器和服务器
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
复制代码
1.1.1 EmbeddedTomcat(默认web服务器)
由条件装配的注解 @ConditionalOnClass
可以看到,当前 classpath 下必须有 Tomcat
这个类,该配置类才会生效
spring-boot-starter-web
中默认导入的是 Tomcat
的依赖
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
复制代码
1.1.2 EmbeddedJetty
导入需要有Server和Loader
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedJetty {
}
复制代码
使用Jetty
需要先排除Tomcat
然后导入Jetty的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Jetty适合长连接应用,就是聊天类的长连接 -->
<!-- 使用Jetty,需要在spring-boot-starter-web排除spring-boot-starter-tomcat,因为SpringBoot默认使用tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
复制代码
1.1.3 EmbeddedUndertow
Undertow它是一个轻量级Web服务器
,但不像传统的 Web 服务器有容器概念,加载一个 Web 应用可以小于 10MB 内存,它提供了对Servlet3.1的支持(支持异步
),对Web Socket
完全支持,用以满足 Web 应用巨大数量的客户端,它不需要容器,只需通过API即可快速搭建Web服务器
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedUndertow {
}
复制代码
使用undertow
也需要先排除Tomcat
然后导入undertow的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
复制代码
1.1.4 ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar
这里会注入两个组件ErrorPageRegistrarBeanPostProcessor(处理错误页面)
和WebServerFactoryCustomizerBeanPostProcessor(用于创建Tomcat容器)
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
// ......
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
// 编程式注入组件
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class);
}
private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
复制代码
1.2 DispatcherServletAutoConfiguration
这里注册了MVC的核心组件DispatcherServlet
// 最高配置优先级
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
// Servlet环境下才生效
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";
// 注册DispatcherServlet的配置类
@Configuration
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
// 启用配置文件与Properties的映射
@EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })
protected static class DispatcherServletConfiguration {
private final HttpProperties httpProperties;
private final WebMvcProperties webMvcProperties;
public DispatcherServletConfiguration(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
this.httpProperties = httpProperties;
this.webMvcProperties = webM