ServletWebServerApplicationContext如何创建Web容器Tomcat

服务器   发布日期:2023年08月27日   浏览次数:316

今天小编给大家分享一下ServletWebServerApplicationContext如何创建Web容器Tomcat的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    正文

    ServletWebServerApplicationContext实现了父类AbstractApplicationContext的onRefresh模板方法,在这里进行了拓展创建了Web容器。

    @Override
    protected void onRefresh() {
       super.onRefresh();
       try {
          createWebServer();
       }
       catch (Throwable ex) {
          throw new ApplicationContextException("Unable to start web server", ex);
       }
    }

    创建Web服务

    private void createWebServer() {
       WebServer webServer = this.webServer;
       ServletContext servletContext = getServletContext();
       if (webServer == null && servletContext == null) {
          //一、获取Web服务器工厂
          ServletWebServerFactory factory = getWebServerFactory();
          //二、获取Web服务
          this.webServer = factory.getWebServer(getSelfInitializer());
          //三、注册Bean生命周期(在容器启动和销毁时调用)
          getBeanFactory().registerSingleton("webServerGracefulShutdown",
                new WebServerGracefulShutdownLifecycle(this.webServer));
          getBeanFactory().registerSingleton("webServerStartStop",
                new WebServerStartStopLifecycle(this, this.webServer));
       }
       else if (servletContext != null) {
          try {
             getSelfInitializer().onStartup(servletContext);
          }
          catch (ServletException ex) {
             throw new ApplicationContextException("Cannot initialize servlet context", ex);
          }
       }
       //四、初始化上下文环境
       initPropertySources();
    }

    一、获取Web服务器工厂

    protected ServletWebServerFactory getWebServerFactory() {
       // Use bean names so that we don't consider the hierarchy
       //获取Web服务器工厂名称
       String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
       if (beanNames.length == 0) {
          throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
                + "ServletWebServerFactory bean.");
       }
       if (beanNames.length > 1) {
          throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
                + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
       }
       //从容器中获取Web服务器工厂实例
       return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }

    这里的Web服务器工厂是通过

    ServletWebServerFactoryAutoConfiguration
    自动配置类导入进来的。
    @Configuration(proxyBeanMethods = false)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @ConditionalOnClass(ServletRequest.class)
    //Web启动环境
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @EnableConfigurationProperties(ServerProperties.class)
    //2.1导入Web工厂
    @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
          ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
          ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
          ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    public class ServletWebServerFactoryAutoConfiguration {
       //导入Web服务器工厂自定义程序
       @Bean
       public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
          return new ServletWebServerFactoryCustomizer(serverProperties);
       }
       //如果是Tomcat则导入Tomcat自定义程序
       @Bean
       @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
       public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
             ServerProperties serverProperties) {
          return new TomcatServletWebServerFactoryCustomizer(serverProperties);
       }
       @Bean
       @ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
       @ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
       public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
          ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
          FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
          registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
          registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
          return registration;
       }
       /**
        * 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);
             }
          }
       }
    }

    1.1 选择导入Web工厂

    @Configuration
    class ServletWebServerFactoryConfiguration {
        ServletWebServerFactoryConfiguration() {
        }
        //1.如果容器中有Servlet,Undertow,SslClientAuthMode就会创建Undertow工厂
        @Configuration
        @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class})
        @ConditionalOnMissingBean(
            value = {ServletWebServerFactory.class},
            search = SearchStrategy.CURRENT
        )
        public static class EmbeddedUndertow {
            public EmbeddedUndertow() {
            }
            @Bean
            public UndertowServletWebServerFactory undertowServletWebServerFactory() {
                return new UndertowServletWebServerFactory();
            }
        }
        //2.如果容器中有Servlet,Server,Loader就会创建Jetty工厂
        @Configuration
        @ConditionalOnClass({Servlet.class, Server.class, Loader.class, WebAppContext.class})
        @ConditionalOnMissingBean(
            value = {ServletWebServerFactory.class},
            search = SearchStrategy.CURRENT
        )
        public static class EmbeddedJetty {
            public EmbeddedJetty() {
            }
            @Bean
            public JettyServletWebServerFactory JettyServletWebServerFactory() {
                return new JettyServletWebServerFactory();
            }
        }
        //3.如果容器中有Servlet,Tomcat,UpgradeProtocol就会创建Tomcat工厂
        @Configuration
        @ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
        @ConditionalOnMissingBean(
            value = {ServletWebServerFactory.class},
            search = SearchStrategy.CURRENT
        )
        public static class EmbeddedTomcat {
            public EmbeddedTomcat() {
            }
            @Bean
            public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
                return new TomcatServletWebServerFactory();
            }
        }
    }

    二、getWebServer:获取Web服务

    public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
    private String protocol = DEFAULT_PROTOCOL;
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat tomcat = new Tomcat();
        // 给嵌入式Tomcat创建一个临时文件夹,用于存放Tomcat运行中需要的文件
        File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        // Tomcat核心概念:Connector,默认放入的protocol为NIO模式
        Connector connector = new Connector(this.protocol);
        // 给Service添加Connector
        tomcat.getService().addConnector(connector);
        // 执行定制器,修改即将设置到Tomcat中的Connector
        customizeConnector(connector);
        tomcat.setConnector(connector);
        // 关闭热部署(嵌入式Tomcat不存在修改web.xml、war包等情况)
        tomcat.getHost().setAutoDeploy(false);
        // 设置backgroundProcessorDelay机制
        configureEngine(tomcat.getEngine());
        for (Connector additionalConnector : this.additionalTomcatConnectors) {
            tomcat.getService().addConnector(additionalConnector);
        }
        // 2.1 创建TomcatEmbeddedContext
        prepareContext(tomcat.getHost(), initializers);
        // 2.2. 创建TomcatWebServer
        return getTomcatWebServer(tomcat);
    }

    2.1 创建TomcatEmbeddedContext

    (注释均已在源码中标注好,小伙伴们对哪一步感兴趣可以借助IDE自己动手Debug体会一下实现)

    protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
        File documentRoot = getValidDocumentRoot();
        // 创建TomcatEmbeddedContext
        TomcatEmbeddedContext context = new TomcatEmbeddedContext();
        if (documentRoot != null) {
            context.setResources(new LoaderHidingResourceRoot(context));
        }
        context.setName(getContextPath());
        context.setDisplayName(getDisplayName());
        // 设置contextPath,很熟悉了
        context.setPath(getContextPath());
        // 给嵌入式Tomcat创建docbase的临时文件夹
        File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase");
        context.setDocBase(docBase.getAbsolutePath());
        // 注册监听器
        context.addLifecycleListener(new FixContextListener());
        context.setParentClassLoader((this.resourceLoader != null) ? this.resourceLoader.getClassLoader()
                : ClassUtils.getDefaultClassLoader());
        // 设置默认编码映射
        resetDefaultLocaleMapping(context);
        addLocaleMappings(context);
        context.setUseRelativeRedirects(false);
        try {
            context.setCreateUploadTargets(true);
        }
        catch (NoSuchMethodError ex) {
            // Tomcat is &lt; 8.5.39. Continue.
        }
        configureTldSkipPatterns(context);
        // 自定义的类加载器,可以加载web应用的jar包
        WebappLoader loader = new WebappLoader(context.getParentClassLoader());
        loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
        // 指定类加载器遵循双亲委派机制
        loader.setDelegate(true);
        context.setLoader(loader);
        // 注册默认的Servlet
        if (isRegisterDefaultServlet()) {
            addDefaultServlet(context);
        }
        // 如果需要jsp支持,注册jsp的Servlet和Initializer
        if (shouldRegisterJspServlet()) {
            addJspServlet(context);
            addJasperInitializer(context);
        }
        // 注册监听器
        context.addLifecycleListener(new StaticResourceConfigurer(context));
        ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
        host.addChild(context);
        configureContext(context, initializersToUse);
        postProcessContext(context);
    }

    2.2. 创建TomcatWebServer

    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
       return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
    }

    进入

    TomcatWebServer
    构造方法中:
    public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
        Assert.notNull(tomcat, "Tomcat Server must not be null");
        this.tomcat = tomcat;
        this.autoStart = autoStart;
        //初始化服务
        initialize();
    }

    初始化TomcatWebServer

    private void initialize() throws WebServerException {
       logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
       synchronized (this.monitor) {
          try {
             //设置Engine的id
             addInstanceIdToEngineName();
             //获取Context(TomcatEmbeddedContext  2.1中创建出来的)
             Context context = findContext();
             //添加监听器 TomcatEmbeddedContext
             //在服务启动时如果有连接进来先删除连接,以便在启动服务时不会发生协议绑定。
             context.addLifecycleListener((event) -> {
                if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
                   // Remove service connectors so that protocol binding doesn't
                   // happen when the service is started.
                   //删除ServiceConnectors,以便在启动服务时不会发生协议绑定。
                   removeServiceConnectors();
                }
             });
             // Start the server to trigger initialization listeners
             //2.2.1 启动Tomcat
             this.tomcat.start();
             // We can re-throw failure exception directly in the main thread
             //Tomcat启动有异常需要在主线程中抛出
             rethrowDeferredStartupExceptions();
             try {
                ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
             }
             catch (NamingException ex) {
                // Naming is not enabled. Continue
             }
             // Unlike Jetty, all Tomcat threads are daemon threads. We create a
             // blocking non-daemon to stop immediate shutdown
             //开启阻塞非守护线程停止web容器
             startDaemonAwaitThread();
          }
          catch (Exception ex) {
             stopSilently();
             destroySilently();
             throw new WebServerException("Unable to start embedded Tomcat", ex);
          }
       }
    }

    2.2.1 启动Tomcat

    创建和初始化Server和Service

    public void start() throws LifecycleException {
        //创建服务(Server和Service)
        getServer();
        server.start();
    }

    启动服务

    public final synchronized void start() throws LifecycleException {
        //如果是正在启动或启动状态
        if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
            }
            return;
        }
        //如果是新建状态
        if (state.equals(LifecycleState.NEW)) {
            //2.2.1.1 初始化服务
            init();
        //如果是失败状态    
        } else if (state.equals(LifecycleState.FAILED)) {
            //停止服务
            stop();
        //如果不是初始化也不是停止状态
        } else if (!state.equals(LifecycleState.INITIALIZED) &amp;&amp;
                !state.equals(LifecycleState.STOPPED)) {
            //修改状态
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }
        try {
            //修改状态为准备启动
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
            //2.2.1.2 启动Internal
            startInternal();
            if (state.equals(LifecycleState.FAILED)) {
                // This is a 'controlled' failure. The component put itself into the
                // FAILED state so call stop() to complete the clean-up.
                stop();
            } else if (!state.equals(LifecycleState.STARTING)) {
                // Shouldn't be necessary but acts as a check that sub-classes are
                // doing what they are supposed to.
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            } else {
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            // This is an 'uncontrolled' failure so put the component into the
            // FAILED state and throw an exception.
            handleSubClassException(t, "lifecycleBase.startFail", toString());
        }
    }

    2.2.1.1 初始化Server

    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        try {
            //设置状态为初始化
            setStateInternal(LifecycleState.INITIALIZING, null, false);
            //初始化
            initInternal();
            //设置状态为初始化完成
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }

    初始化 Server

    protected void initInternal() throws LifecycleException {
        //调用父类初始化(设置名称:Tomcat,类型:Server)
        super.initInternal();
        // Initialize utility executor
        reconfigureUtilityExecutor(getUtilityThreadsInternal(utilityThreads));
        //注册线程池
        register(utilityExecutor, "type=UtilityExecutor");
        // Register global String cache
        // Note although the cache is global, if there are multiple Servers
        // present in the JVM (may happen when embedding) then the same cache
        // will be registered under multiple names
        //注册字符串缓存
        onameStringCache = register(new StringCache(), "type=StringCache");
        // Register the MBeanFactory
        MBeanFactory factory = new MBeanFactory();
        factory.setContainer(this);
        //注册Bean工厂
        onameMBeanFactory = register(factory, "type=MBeanFactory");
        // Register the naming resources
        //注册命名资源
        globalNamingResources.init();
        // Populate the extension validator with JARs from common and shared
        // class loaders
        if (getCatalina() != null) {
            ClassLoader cl = getCatalina().getParentClassLoader();
            // Walk the class loader hierarchy. Stop at the system class loader.
            // This will add the shared (if present) and common class loaders
            while (cl != null &amp;&amp; cl != ClassLoader.getSystemClassLoader()) {
                if (cl instanceof URLClassLoader) {
                    URL[] urls = ((URLClassLoader) cl).getURLs();
                    for (URL url : urls) {
                        if (url.getProtocol().equals("file")) {
                            try {
                                File f = new File (url.toURI());
                                if (f.isFile() &amp;&amp;
                                        f.getName().endsWith(".jar")) {
                                    ExtensionValidator.addSystemResource(f);
                                }
                            } catch (URISyntaxException e) {
                                // Ignore
                            } catch (IOException e) {
                                // Ignore
                            }
                        }
                    }
                }
                cl = cl.getParent();
            }
        }
        // Initialize our defined Services
        //2.2.1.1.1 初始化service(2.2.1最开始时创建)
        for (Service service : services) {
            service.init();
        }
    }

    初始化Service

    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        try {
            //设置状态为初始化
            setStateInternal(LifecycleState.INITIALIZING, null, false);
            //初始化
            initInternal();
            //设置状态为初始化完成
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }

    初始化Service

    protected void initInternal() throws LifecycleException {
        //调用父类初始化(设置名称:Tomcat,类型:Server)
        super.initInternal();
        //2.2.1.1.1.1 初始化engine
        if (engine != null) {
            engine.init();
        }
        // Initialize any Executors
        //2.2.1.1.1.2 初始化executor
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            executor.init();
        }
        // Initialize mapper listener
        //2.2.1.1.1.3 初始化mapperListener
        mapperListener.init();
        // Initialize our defined Connectors
        //2.2.1.1.1.4 初始化connector
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
                connector.init();
            }
        }
    }

    初始化engine

    protected void initInternal() throws LifecycleException {
        // Ensure that a Realm is present before any attempt is made to start
        // one. This will create the default NullRealm if necessary.
        // 在尝试启动一个Realm之前,请确保存在一个Realm。如有必要,这将创建默认的NullRealm
        getRealm();
        super.initInternal();
    }
    public Realm getRealm() {
        Realm configured = super.getRealm();
        // If no set realm has been called - default to NullRealm
        // This can be overridden at engine, context and host level
        if (configured == null) {
            configured = new NullRealm();
            this.setRealm(configured);
        }
        return configured;
    }

    初始化executor

    它还是调的父类

    LifecycleMBeanBase
    的方法
    protected void initInternal() throws LifecycleException {
        super.initInternal();
    }

    初始化mapperListener

    protected void initInternal() throws LifecycleException {
        // If oname is not null then registration has already happened via preRegister().
        // 如果oname不为null,则已经通过preRegister()进行了注册
        if (oname == null) {
            mserver = Registry.getRegistry(null, null).getMBeanServer();
            oname = register(this, getObjectNameKeyProperties());
        }
    }

    初始化connector

    protected void initInternal() throws LifecycleException {
        super.initInternal();
        if (protocolHandler == null) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
        }
        // Initialize adapter
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);
        if (service != null) {
            protocolHandler.setUtilityExecutor(service.getServer().getUtilityExecutor());
        }
        // Make sure parseBodyMethodsSet has a default
        if (null == parseBodyMethodsSet) {
            setParseBodyMethods(getParseBodyMethods());
        }
        if (protocolHandler.isAprRequired() &amp;&amp; !AprStatus.isInstanceCreated()) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
                    getProtocolHandlerClassName()));
        }
        if (protocolHandler.isAprRequired() &amp;&amp; !AprStatus.isAprAvailable()) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
                    getProtocolHandlerClassName()));
        }
        if (AprStatus.isAprAvailable() &amp;&amp; AprStatus.getUseOpenSSL() &amp;&amp;
       &a						
    						
    						
    						
    						
    						
    						
    					

    以上就是ServletWebServerApplicationContext如何创建Web容器Tomcat的详细内容,更多关于ServletWebServerApplicationContext如何创建Web容器Tomcat的资料请关注九品源码其它相关文章!