、Tomcat源码分析-spring boot集成tomcat

tomcat 外部配置

前面我们分析了 spring boot 与 tomcat 的集成,我们再来看看 spring boot 是如何为 serlvet 容器设置参数的。首先,来看一下常用的配置,内嵌容器的配置以 server 开头,下面的示例采用 yml 格式,properties 文件只是格式略有不同而已

application.yml

server:
  port: 8080
  context-path: /driver
  tomcat:
    max-threads: 500
    max-connections: 20000 # 最大允许的连接数,nio默认10000

spring boot 关于内嵌 servlet 容器主要依赖 ServerProperties 完成,下面的代码列举了常用的配置,注意:代码里面的 TomcatJetty 是内部类,用于进行参数配置的,并不是对应的 servlet 容器。比如我们要设置 tomcat 的参数,使用 server.tomcat 前缀即可,jetty 对应就是 server.jetty

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties
        implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {

    private Integer port;
    private String contextPath;
    private String servletPath = "/";

    private final Tomcat tomcat = new Tomcat();
    private final Jetty jetty = new Jetty();
    private final Undertow undertow = new Undertow();

    public static class Tomcat {
        private final Accesslog accesslog = new Accesslog();
        private int maxThreads = 0; // Number of threads in protocol handler
        private int maxConnections = 0;
        private int acceptCount = 0;
    }

    public static class Jetty { //...... }

    public static class Undertow {  //...... }

    //......

spring boot 是如何为 servlet 容器设置这些参数的呢?我们注意到 ServerProperties 实现了 EmbeddedServletContainerCustomizer 接口,通过这个接口便可以进行参数设置,下面列出了部分代码。首先,对通用参数进行设置,比如 端口上下文路径session 超时时间 等等,然后判断 ConfigurableEmbeddedServletContainer 的具体实现类,分别对具体的 servlet 容器进行配置,因为不同 servlet 容器的参数是不一样的,所以需要特殊处理。如果我们需要对 tomcat 容器进行额外的设置,可以实现 EmbeddedServletContainerCustomizer 接口,然后把这个 bean 注册到 spring 容器中即可

@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
    if (getPort() != null) {
        container.setPort(getPort());
    }
    // other code......

    // 根据具体的实现类,分别对具体的 servlet 容器进行配置
    if (container instanceof TomcatEmbeddedServletContainerFactory) {
        // 即 private final Tomcat tomcat = new Tomcat();
        getTomcat().customizeTomcat(this,
                (TomcatEmbeddedServletContainerFactory) container);
    }
    if (container instanceof JettyEmbeddedServletContainerFactory) {
        getJetty().customizeJetty(this,
                (JettyEmbeddedServletContainerFactory) container);
    }

    if (container instanceof UndertowEmbeddedServletContainerFactory) {
        getUndertow().customizeUndertow(this,
                (UndertowEmbeddedServletContainerFactory) container);
    }
    container.addInitializers(new SessionConfiguringInitializer(this.session));
    container.addInitializers(new InitParameterConfiguringServletContextInitializer(
            getContextParameters()));

EmbeddedServletContainerCustomizer 又是何时被调用的呢?它是通过 BeanPostProcessor 进行扩展实现的,从 spring 容器中获取 ConfigurableEmbeddedServletContainer 对象时,便会执行该 BeanPostProcessor,这里再次感受到 BeanPostProcessor 的强大之处。

public class EmbeddedServletContainerCustomizerBeanPostProcessor
        implements BeanPostProcessor, BeanFactoryAware {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        if (bean instanceof ConfigurableEmbeddedServletContainer) {
            postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
        }
        return bean;
    }

    private void postProcessBeforeInitialization(ConfigurableEmbeddedServletContainer bean) {
        for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
            customizer.customize(bean);
        }
    }

总结

在此,spring boot 集成 tomcat 的代码分析便告一段落,最后,我们用一张图总结下整个逻辑(查看原图)

  • spring boot 利用 spring 的 SPI 的机制加载 EmbeddedServletContainerAutoConfiguration 该配置类,将 TomcatEmbeddedServletContainerFactory 加载到 spring 容器中
  • 对 tomcat 容器进行配置的动作,由 BeanFactoryPostProcessor 完成,spring boot 内置了多种 EmbeddedServletContainerCustomizer,由 ServerConfig 完成对 servlet 容器的配置
  • 利用工厂模式创建 TomcatEmbeddedServletContainer,并且调用 org.apache.catalina.startup.Tomcat#start() 启动 tomcat 容器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java面试大全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值