栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot tomcat定制化实现原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot tomcat定制化实现原理

SpringBoot Tomcat 定制化实现原理

SpringBoot Tomcat 配置定制化,可以通过两种方式:

  1. Springboot 默认提供属性配置,比如server.tomcat.XXX
  2. 通过编程方式实现Tomcat 属性配置,通过编程方式有两种方法
    1. 实现TomcatConnectorCustomizer/TomcatContextCustomizer/TomcatProtocolHandlerCustomizer
    2. 实现WebServerFactoryCustomizer,并实现Ordered接口
SpringBoot 默认提供Tomcat属性配置

springbootTomcat 常用配置如下:

属性属性默认值属性说明
basedir默认为临时目录tomcat 运行目录–建议覆盖默认配置
threads.max默认为200tomcat 最大线程数
threads.minSpare默认为10tomcat 最小线程数
uriEncoding默认为UTF8URI编码格式
maxConnections默认为8192tomcat 最大连接数
acceptCount默认为100接请求的最大队列长度
connectionTimeout默认为6秒连接超时时间
编程方式实现Tomcat属性配置 通过TomcatXXXCustomizer来实现
@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(
				ObjectProvider connectorCustomizers,
				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();
	}

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643180.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号