跟踪springboot自启动tomcat
工作需要修改内置tomcat连接参数,将自己分析前后分享。
springboot 内置tomcat,tomcat为自动开启的配置,进入@SpringBootApplication注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
springboot原理,就是使用SpingFactoriesLoader.loadFactoryNames 扫描具有META-INFO/spring.factories文件的jar包 。
加载容器的配置文件 EmbeddedServletContainerAutoConfiguration,在配置文件中,内置tomcat(满足tomcat容器条件的bean存在),只要满足Jetty、Undertow的条件,可以切换为其他容器。
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Undertow is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
@Bean
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory();
}
}
以tomcat为例,继续看如何加载并配置servlet容器 TomcatEmbeddedServletContainerFactory 获取容器
@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatEmbeddedServletContainer(tomcat);
}
继续跟踪查看customizeConnector(connector);
查看此方法源码 所以有两种方式可以实现个性化的connector
1.继承 TomcatEmbeddedServletContainerFactory 重写此方法,加入个性化配置
2.实现TomcatConnectorCustomizer 接口,将实现类加入到TomcatEmbeddedServletContainerFactory
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
customizer.customize(connector);
}
public void addConnectorCustomizers(
TomcatConnectorCustomizer... tomcatConnectorCustomizers) {
Assert.notNull(tomcatConnectorCustomizers,
"TomcatConnectorCustomizers must not be null");
this.tomcatConnectorCustomizers.addAll(Arrays.asList(tomcatConnectorCustomizers));
}
TomcatConnectorCustomizer 自定义个性化connector(实现此类后,将实现类接入到factory中即可)
public interface TomcatConnectorCustomizer {
/**
* Customize the connector.
* @param connector the connector to customize
*/
void customize(Connector connector);
}