Blog

  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

SpringBoot自动装配--嵌入式Servlet容器

发表于 2019-08-18 分类于 SpringBoot 阅读次数:
本文字数: 9.8k

简介

一般做Springboot项目,都是打成jar包,并且内嵌一个Servlet容器(Tomcat,jetty,undertow),今天就了解一下有关内嵌Servlet容器的自动装配(2.0.0版本),主要是两个类EmbeddedWebServerFactoryCustomizerAutoConfiguration和ServletWebServerFactoryAutoConfiguration

EmbeddedWebServerFactoryCustomizerAutoConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Configuration
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {

@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {

@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}

/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
public static class JettyWebServerFactoryCustomizerConfiguration {

@Bean
public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new JettyWebServerFactoryCustomizer(environment, serverProperties);
}

}

/**
* Nested configuration if Undertow is being used.
*/
@Configuration
@ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
public static class UndertowWebServerFactoryCustomizerConfiguration {

@Bean
public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
}

}

}

根据导入的依赖不同,会注册不同的WebServerFactoryCustomizer(容器工厂定制器),默认在spring-boot-starter-web中会依赖spring-boot-starter-tomcat,即默认使用的是Tomcat容器,如果想用其他的容器,就将默认的依赖删除,加入指定容器的依赖即可。就以TomcatWebServerFactoryCustomizer为例:

ServerProperties

1
2
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {}

从配置文件中读取属性值。

TomcatWebServerFactoryCustomizer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class TomcatWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered {

private final Environment environment;

private final ServerProperties serverProperties;

public TomcatWebServerFactoryCustomizer(Environment environment,
ServerProperties serverProperties) {
this.environment = environment;
this.serverProperties = serverProperties;
}

@Override
public void customize(ConfigurableTomcatWebServerFactory factory) {
ServerProperties properties = this.serverProperties;
ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
PropertyMapper propertyMapper = PropertyMapper.get();
propertyMapper.from(tomcatProperties::getBasedir).whenNonNull()
.to(factory::setBaseDirectory);
propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull()
.as(Duration::getSeconds).as(Long::intValue)
.to(factory::setBackgroundProcessorDelay);
customizeRemoteIpValve(factory);
propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive)
.to((maxThreads) -> customizeMaxThreads(factory,
tomcatProperties.getMaxThreads()));
propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
propertyMapper.from(() -> determineMaxHttpHeaderSize()).when(this::isPositive)
.to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
maxHttpHeaderSize));
propertyMapper.from(tomcatProperties::getMaxHttpPostSize)
.when((maxHttpPostSize) -> maxHttpPostSize != 0)
.to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory,
maxHttpPostSize));
propertyMapper.from(tomcatProperties::getAccesslog)
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
.to((enabled) -> customizeAccessLog(factory));
propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull()
.to(factory::setUriEncoding);
propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
.to((connectionTimeout) -> customizeConnectionTimeout(factory,
connectionTimeout));
propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)
.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)
.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
customizeStaticResources(factory);
customizeErrorReportValve(properties.getError(), factory);
}
}

TomcatWebServerFactoryCustomizer 实现了 WebServerFactoryCustomizer接口,其中有一个customize方法,是根据ServerProperties(配置文件中的配置)给容器进行初始化,打个断点,观察一下方法调用栈。

发现是WebServerFactoryCustomizerBeanPostProcessor这个后置处理器中调用的

WebServerFactoryCustomizerBeanPostProcessor

1
2
3
4
5
6
7
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
LambdaSafe
.callbacks(WebServerFactoryCustomizer.class, getCustomizers(),
webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}

这里会获取所有的WebServerFactoryCustomizer,依次调用其中的customize方法。

WebServerFactoryCustomizer

这些都是WebServerFactoryCustomizer接口的实现类,可以发现其中的TomcatServletWebServerFactoryCustomizer,ServletWebServerFactoryCustomizer,TomcatWebServerFactoryCustomizer都是和Tomcat有关的。

  • TomcatWebServerFactoryCustomizer 配置tomcat的主要信息,包含remoteIpValue、connector(最大/最小可接收线程、最大可接收头部大小等等)、uriEncoding、connectionTimeout、maxConnection等属性
  • TomcatServletWebServerFactoryCustomizer 配置tomcat的额外信息,redirectContextRoot(是否在请求根上下文时转发,true则转发路径为/demoWeb/)和useRelativeRedirects(是否使用相对路径)等路径跳转问题处理
  • ServletWebServerFactoryCustomizer 主要配置tomcat的servlet的信息,包含端口、上下文路径、应用名、Session配置、Servlet携带的初始变量等等

ServletWebServerFactoryAutoConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@Configuration
@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 {

@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}

@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}

/**
* Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
* {@link ImportBeanDefinitionRegistrar} for early registration.
*/
public static class BeanPostProcessorsRegistrar
implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

private ConfigurableListableBeanFactory beanFactory;

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}

@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);
}
}
}
}

可以发现,ServletWebServerFactoryAutoConfiguration这个自动装配的类中注册了这两个容器工厂定制器。并且@import(BeanPostProcessorsRegistrar),其中注册了webServerFactoryCustomizerBeanPostProcessor这个后置处理器。

自定义webServerFactoryCustomizer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Bean
public WebServerFactoryCustomizer myWebServerFactoryCustomizer() {
return (WebServerFactory factory) -> {
System.out.println("I am myWebServerFactoryCustomizer");
if (factory instanceof AbstractConfigurableWebServerFactory) {
((AbstractConfigurableWebServerFactory) factory).setPort(8002);
}
};
}
// return new WebServerFactoryCustomizer() {
// @Override
// public void customize(WebServerFactory factory) {
// System.out.println("I am myWebServerFactoryCustomizer");
// if(factory instanceof AbstractConfigurableWebServerFactory){
// ((AbstractConfigurableWebServerFactory) factory).setPort(8002);
// }
// }
// };

可以在自定义一个WebServerFactoryCustomizer,设置自定义的属性。

总结

springboot在启动时,会自动装配EmbeddedWebServerFactoryCustomizerAutoConfiguration和ServletWebServerFactoryAutoConfiguration。其中会有一些相关的Customizer(定制器),并注册了webServerFactoryCustomizerBeanPostProcessor后置处理器。然后在创建Servlet容器时,会在这个后置处理器中遍历这些定制器,完成对Servlet容器属性的设置。


------ 已触及底线感谢您的阅读 ------
麻辣香锅不要辣 微信支付

微信支付

  • 本文作者: 麻辣香锅不要辣
  • 本文链接: https://http://ybhub.gitee.io/2019/08/18/Springboot-EmbeddedWebServerAutoConfiguration/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
# SpringBoot # 自动装配
SpringBoot自动装配--ErrorMvcAutoConfiguration
springboot启动配置原理
  • 文章目录
  • 站点概览
麻辣香锅不要辣

麻辣香锅不要辣

21 日志
11 分类
20 标签
GitHub 简书
  1. 1. 简介
  2. 2. EmbeddedWebServerFactoryCustomizerAutoConfiguration
    1. 2.1. ServerProperties
    2. 2.2. TomcatWebServerFactoryCustomizer
    3. 2.3. WebServerFactoryCustomizerBeanPostProcessor
    4. 2.4. WebServerFactoryCustomizer
    5. 2.5. ServletWebServerFactoryAutoConfiguration
  3. 3. 自定义webServerFactoryCustomizer
  4. 4. 总结
© 2019 – 2020 麻辣香锅不要辣 | 站点总字数: 20.4k字
|
0%