SpringBoot Tomcat 配置定制化,可以通过两种方式:
- Springboot 默认提供属性配置,比如server.tomcat.XXX
- 通过编程方式实现Tomcat 属性配置,通过编程方式有两种方法
1. 实现TomcatConnectorCustomizer/TomcatContextCustomizer/TomcatProtocolHandlerCustomizer
2. 实现WebServerFactoryCustomizer,并实现Ordered接口
springbootTomcat 常用配置如下:
| 属性 | 属性默认值 | 属性说明 |
|---|---|---|
| basedir | 默认为临时目录 | tomcat 运行目录–建议覆盖默认配置 |
| threads.max | 默认为200 | tomcat 最大线程数 |
| threads.minSpare | 默认为10 | tomcat 最小线程数 |
| uriEncoding | 默认为UTF8 | URI编码格式 |
| maxConnections | 默认为8192 | tomcat 最大连接数 |
| acceptCount | 默认为100 | 接请求的最大队列长度 |
| connectionTimeout | 默认为6秒 | 连接超时时间 |
@Configuration(proxyBeanMethods = false)
public class MyTomcatConnector implements TomcatConnectorCustomizer {
@Override
public void customize(Connector connector) {
connector.setPort(9090);
System.out.println("connector设置为9090" );
}
}
通过WebServerFactoryCustomizer来实现
@Configuration @Order(3) public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer探讨下两种配置方式的优先级问题, ApplicationContextAware { private ApplicationContext context; @Override public void customize(TomcatServletWebServerFactory factory) { if (context instanceof WebServerApplicationContext) { TomcatWebServer webServer = ((TomcatWebServer) ((WebServerApplicationContext) context).getWebServer()); //webServer.getTomcat().setPort(9091); } factory.setPort(9091); System.out.println("connector设置为9091"); Connector ajp = new Connector("AJP/1.3"); ajp.setPort(8085); ajp.setSecure(false); ajp.setScheme("http"); AjpNioProtocol ajpNioProtocol = (AjpNioProtocol) ajp.getProtocolHandler(); ajpNioProtocol.setSecretRequired(false); factory.addAdditionalTomcatConnectors(ajp); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; } }
Springboot 默认提供属性配置< WebServerFactoryCustomizer(order>0) < TomcatXXXCustomizer
- 默认WebServerFactoryCustomizer优先级低于TomcatXXXCustomizer,就是TomcatXXXCustomizer会覆盖WebServerFactoryCustomizer的属性配置。
- WebServerFactoryCustomizer 基于WebServerFactoryCustomizerBeanPostProcessor来实现属性赋值
- SpringBoot提供tomcat属性配置基于TomcatWebServerFactoryCustomizer来实现,默认优先级为0
源码解析 TomcatXXXCustomizer
- 收集TomcatXXXCustomizer的bean
@Bean //收集TomcatXXXCustomizer的bean TomcatServletWebServerFactory tomcatServletWebServerFactory( ObjectProviderconnectorCustomizers, ObjectProvider contextCustomizers, ObjectProvider > protocolHandlerCustomizers) { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.getTomcatConnectorCustomizers() .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList())); factory.getTomcatContextCustomizers() .addAll(contextCustomizers.orderedStream().collect(Collectors.toList())); factory.getTomcatProtocolHandlerCustomizers() .addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList())); return factory; }
- 调用TomcatXXXCustomizer来自于org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setbaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
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 getTomcatWebServer(tomcat);
}
WebServerFactoryCustomizer
public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"WebServerCustomizerBeanPostProcessor can only be used with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebServerFactory) {
//关键点
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
private Collection> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
//获取spring 容器里面所有的WebServerFactoryCustomizer bean,如果没有实例化进行实例化
private Collection> getWebServerFactoryCustomizerBeans() {
return (Collection) this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
}



