精华内容
下载资源
问答
  • 小编典典您需要实现ServletContextListner接口,并在其中启动要在tomcat启动时执行的代码。这有关它的简短描述。ServletContextListner在javax.servlet包中。这有关如何执行的简短代码。public class ...

    小编典典

    您需要实现ServletContextListner接口,并在其中启动要在tomcat启动时执行的代码。

    这是有关它的简短描述。

    ServletContextListner在javax.servlet包中。

    这是有关如何执行的简短代码。

    public class MyServletContextListener implements ServletContextListener {

    @Override

    public void contextDestroyed(ServletContextEvent arg0) {

    //Notification that the servlet context is about to be shut down.

    }

    @Override

    public void contextInitialized(ServletContextEvent arg0) {

    // do all the tasks that you need to perform just after the server starts

    //Notification that the web application initialization process is starting

    }

    }

    并且您需要在部署描述符web.xml中对其进行配置

    mypackage.MyServletContextListener

    2020-06-16

    展开全文
  • 本文是我阅读了Tomcat源码后的一些心得。 主要是讲解Tomcat的系统框架,启动流程已经运行过程。若有错漏之处,敬请...tomcat是如何及什么时候创建线程来处理请求的? tomcat的配置文件context.xml,server.xml,tomca

    本文是我阅读了Tomcat源码后的一些心得。主要是讲解Tomcat的系统框架,启动流程已经运行过程。若有错漏之处,敬请批评指教。

         先给出几个问题:

    tomcat作为一个应用服务器的程序入口在哪里?

    tomcat的整体组件结构是什么样的?

    tomcat是什么时候及如何创建线程来处理请求的?

    tomcat的配置文件context.xml,server.xml,tomcat-users.xml,web.xml什么时候加载的及作用是什么?

    最后,tomcat是如何启动运行的?

    我通过源码来分析这些问题。

           tomcat作为最常见的应用服务器,对ServerSocketSocket封装使用TCP链接达到通信的目的,我从它的程序入口开始跟踪代码,看它是如何启动的。

         Tomcat组件有ServerServiceContainerConnectorEngineHostContextProtocolHandlerEndPoint

    Server一个Server元素代表一整个CatalinaServlet容器,也就是说Server是最顶级的容器,它包含一个或多个Service,这个在后面我们可以看到;

    Service由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求;

    Connector连接器,一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户;

    EngineEngine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理;

    HostHost获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理;

    Context一个Context对应于一个WebApplication,一个WebApplication由一个或者多个Servlet组成(这个就是我们熟悉的上下文对象了);

    ContainerEngineHostContext的父类或父接口,这里使用了Composite组合模式,调用它们的start()方法时都会调用父类的此方法;

    ProtocolHandler协议处理器,连接器持有用来控制网络端口监听组件运行;

    EndPoint负责监控网络端口的组件,启动一个ServerSocket,不间断监听来自客户端的请求。

         当我们启动Tomcat时:程序会找到Bootstrapmain()方法,同时把args置为["start"]:


    然后程序会执行init()方法,设置tomcat运行的环境,初始化类加载器,创建Catalina对象:


    接下来程序会执行load()start()方法,这是tomcat启动过程中最重要的两个过程,load()其实是初始化一系列的组件,上面所列的组件都会进行初始化,包括加载配置文件都是在这个过程中实现的;而start()方法就是启动这一系列的组件,当所有组件都启动后,tomcat也就启动完成了。

    从这里看,Tomcat启动过程可以简化为3个步骤:

    1Bootstrapinit()方法,其实就是设置运行环境和初始化类加载器;

    2Bootstrapload()方法,加载相关配置文件,初始化几个主要的顶层组件实例,也就是服务器初始化。

    3)启动那些有生命周期的组件,监听用户请求,也就是启动服务器。

            load()方法其实是通过反射来执行Catalinaload()方法,Catalinaload()方法主要作用:

                  initDirs()方法初始化tomcat的安装路径;

                   createStartDigester()方法解析xml文件;

                  getServer().initialize()方法初始化Server组件。



    接下来我们看一下server.xml里面的信息到底是什么?为什么能创建server对象呢?


    这个就是server.xml的内容,我们可以清晰的看到server下面包含serviceservice下面包含connectorconnector下面包含enginehostcontext,这些就是我们上面所说的tomcat的组件,他们的对应关系也是这样层层包含的关系。

               接下来看看Server真正的初始化过程:StandardServerinitialize():


    StandardServiceinitialize()



    初始化connectorConnectorinitialize()



    初始化协议,Http11Protocolinit()


    Endpoint的初始化,Endpointinit()


    根据上面的server.xml,connector有两个,所以会初始化两个connectorProtocolHandlerendpoint;

    初始化的流程:


    所以我们可以知道Bootstrap#load()—>Catalina#load()—>StandardServer#load()—>StandardService#initialize()—>Connector#initialize()—>Http11Protocol#init()—>Endpoint#init()

    至此,tomcat的初始化全部完成。



    接下来开始启动tomcat服务器:

    回到Bootstrap来,Bootstrapstart()方法通过反射来调用Catalina方法的start()方法

    来看看Catalinastart()


    StandardServerstart()


    下面就看看StandardService对象的start方法:

    首先启动Container容器,在server.xml中我们知道Container中含有EngineHostContext,所以这里会启动这三个容器,Service中的这个ContainerEngine,所以首先会启动EngineEngine中有HostContext,它们又都属于Container,所以,这里充分的利用了组合模式,这个过程中会创建background后台守护线程,周期性的检查Session是否超时

    然后启动执行器executors,这里executors一般为null

    最后启动所有的Connector,这个过程会启动两组ProtocolHandlerEndpoint,这个过程是很重要的一个过程,会创建所有的请求线程池,首先先创建一个Acceptor线程来监听当前线程是否够用,若不够用则会创建线程池用来处理http请求;另外一组ProtocolHandlerEndpoint是用来处理apj请求,会创建TP-MonitorTP-Processor线程池


    StandardService下的容器有Container,这个Container其实就是EngineEngine下的容器有HostHost下的容器有Context

    每个容器下都有PipelineValueRealm等等配置。

    接下来就看看如何启动这些各个容器的:


    父类的start()方法:每个container子类都会调用,根据当前对象读取不同的children,然后递归调用childrenstart()方法



    启动background后台守护线程,周期性的检查Session是否超时:


    此时我们可以清楚的看到background线程已经启动




    所有的container启动完毕后,接下来回到StandardServicestart()来:接下来执行Connectorstart()


    Http11Protocolstart():委托给JioEndpoint调用start()方法,真正跟serverSocket有关的都在endpoint中执行


    JIoEndpointstart():启动endpoint实际上是启动一个acceptor线程,这个线程很重要,在这个线程里面判断当前的http线程是否足够,若不够则从线程池中创建线程来处理http请求,所以,就是在这里创建的线程来处理请求的


    接下来我们看看Accptor类的run()方法中究竟写了什么:



    到这里,我们就创建了acceptor线程和http线程池了。




    接下来处理另外一个connector:这里用的协议处理器是JkCoyoteHandlerJkCoyoteHandlerstart()


    启动jkMain


    最后,在channelSocketinit()方法中启动TP-MonitorTP-Processor线程池:



    此时,我们可以看到TP-MonitorTP-Processor线程已经启动:




    所以我们可以知道tomcat容器的启动过程:

    Bootstrap#start()—>Catalina#start()—>StandardServer#start()—>StandardService#start()—>Connector#start()—>Http11Protocol#start()—>Endpoint#init()—>acceptorThread.start()启动请求线程池

    StandardService#start()—>StandardEngine#start()—>ContainerBase#start()—>StandardHost#start()—>ContainerBase#start()—>StandardContext#start()—>ContainerBase#start()(启动守护线程)

    至此,tomcat的初始化全部完成。


    至此,tomcat服务器已完全启动了。

    启动的时序图如下:



    TomcatServer处理一个http请求的过程

    1)当来了一个http请求,acceptor线程先判断现在已存在的线程是否足够,若不足够,则创建一个线程来处理请求,足够就使用已存在的;



    2)SocketProcessor来处理请求


    3)Http11ConnectionHandlerprocess()方法处理:


    4)Http11Processorprocess()



    5)CoyoteAdapterservice()


    6)StandardEngineValveinvoke()


    7)StandardHostValveinvoke()


    8)StandardContextValveinvoke()


    9)StandardWraValveinvoke()


    总的流程如下:


    展开全文
  • 本文是我阅读了Tomcat源码后的一些心得。主要是讲解Tomcat的系统框架,启动流程已经运行过程。...tomcat是什么时候及如何创建线程来处理请求的? tomcat的配置文件context.xml,server.xml,tomcat

    本文是我阅读了Tomcat源码后的一些心得。主要是讲解Tomcat的系统框架,启动流程已经运行过程。若有错漏之处,敬请批评指教。

    先给出几个问题:

    tomcat作为一个应用服务器的程序入口在哪里?

    tomcat的整体组件结构是什么样的?

    tomcat是什么时候及如何创建线程来处理请求的?

    tomcat的配置文件context.xml,server.xml,tomcat-users.xml,web.xml什么时候加载的及作用是什么?

    最后,tomcat是如何启动运行的?

    我通过源码来分析这些问题。

    tomcat作为最常见的应用服务器,对ServerSocket、Socket封装使用TCP链接达到通信的目的,我从它的程序入口开始跟踪代码,看它是如何启动的。

    Tomcat组件有Server,Service,Container,Connector,Engine,Host,Context,ProtocolHandler,EndPoint等

    Server:一个Server元素代表一整个CatalinaServlet容器,也就是说Server是最顶级的容器,它包含一个或多个Service,这个在后面我们可以看到;

    Service:由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求;

    Connector:连接器,一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户;

    Engine:当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理;

    Host:当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理;

    Context:一个Context对应于一个WebApplication,一个WebApplication由一个或者多个Servlet组成(这个就是我们熟悉的上下文对象了);

    Container:是Engine,Host,Context的父类或父接口,这里使用了Composite组合模式,调用它们的start()方法时都会调用父类的此方法;

    ProtocolHandler:协议处理器,连接器持有用来控制网络端口监听组件运行;

    EndPoint:负责监控网络端口的组件,启动一个ServerSocket,不间断监听来自客户端的请求。

    当我们启动Tomcat时:程序会找到Bootstrap的main()方法,同时把args置为["start"]:

     

    \

     

    然后程序会执行init()方法,设置tomcat运行的环境,初始化类加载器,创建Catalina对象:

     

    \

     

    接下来程序会执行load()和start()方法,这是tomcat启动过程中最重要的两个过程,load()其实是初始化一系列的组件,上面所列的组件都会进行初始化,包括加载配置文件都是在这个过程中实现的;而start()方法就是启动这一系列的组件,当所有组件都启动后,tomcat也就启动完成了。

    从这里看,Tomcat启动过程可以简化为3个步骤:

    1)Bootstrap的init()方法,其实就是设置运行环境和初始化类加载器;

    2)Bootstrap的load()方法,加载相关配置文件,初始化几个主要的顶层组件实例,也就是服务器初始化。

    3)启动那些有生命周期的组件,监听用户请求,也就是启动服务器。

    load()方法其实是通过反射来执行Catalina的load()方法,Catalina的load()方法主要作用:

    initDirs()方法初始化tomcat的安装路径;

    createStartDigester()方法解析xml文件;

    getServer().initialize()方法初始化Server组件。

     

    \

     

     

    \

     

    接下来我们看一下server.xml里面的信息到底是什么?为什么能创建server对象呢?

     

    \

     

    这个就是server.xml的内容,我们可以清晰的看到server下面包含service,service下面包含connector,connector下面包含engine,host和context,这些就是我们上面所说的tomcat的组件,他们的对应关系也是这样层层包含的关系。

    接下来看看Server真正的初始化过程:StandardServer的initialize():

     

    \

     

    StandardService的initialize():

     

    \

     

     

    \

     

    初始化connector,Connector的initialize():

     

    \

     

     

    \

     

    初始化协议,Http11Protocol的init():

     

    \

     

    Endpoint的初始化,Endpoint的init():

     

    \

     

    根据上面的server.xml,connector有两个,所以会初始化两个connector,ProtocolHandler和endpoint;

    初始化的流程:

     

    \

     

    所以我们可以知道Bootstrap#load()—>Catalina#load()—>StandardServer#load()—>StandardService#initialize()—>Connector#initialize()—>Http11Protocol#init()—>Endpoint#init()

    至此,tomcat的初始化全部完成。

    接下来开始启动tomcat服务器:

    回到Bootstrap来,Bootstrap的start()方法通过反射来调用Catalina方法的start()方法

    来看看Catalina的start():

     

    \

     

    StandardServer的start():

     

    \

     

    下面就看看StandardService对象的start方法:

    首先启动Container容器,在server.xml中我们知道Container中含有Engine,Host,Context,所以这里会启动这三个容器,Service中的这个Container是Engine,所以首先会启动Engine,Engine中有Host和Context,它们又都属于Container,所以,这里充分的利用了组合模式,这个过程中会创建background后台守护线程,周期性的检查Session是否超时

    然后启动执行器executors,这里executors一般为null

    最后启动所有的Connector,这个过程会启动两组ProtocolHandler和Endpoint,这个过程是很重要的一个过程,会创建所有的请求线程池,首先先创建一个Acceptor线程来监听当前线程是否够用,若不够用则会创建线程池用来处理http请求;另外一组ProtocolHandler和Endpoint是用来处理apj请求,会创建TP-Monitor和TP-Processor线程池

     

    \

     

    StandardService下的容器有Container,这个Container其实就是Engine,Engine下的容器有Host,Host下的容器有Context。

    每个容器下都有Pipeline、Value、Realm等等配置。

    接下来就看看如何启动这些各个容器的:

     

    \

     

    父类的start()方法:每个container子类都会调用,根据当前对象读取不同的children,然后递归调用children的start()方法

     

    \

     

     

    \

     

    启动background后台守护线程,周期性的检查Session是否超时:

     

    \

     

    此时我们可以清楚的看到background线程已经启动

     

    \

     

    所有的container启动完毕后,接下来回到StandardService的start()来:接下来执行Connector的start():

     

    \

     

    Http11Protocol的start():委托给JioEndpoint调用start()方法,真正跟serverSocket有关的都在endpoint中执行

     

    \

     

    JIoEndpoint的start():启动endpoint实际上是启动一个acceptor线程,这个线程很重要,在这个线程里面判断当前的http线程是否足够,若不够则从线程池中创建线程来处理http请求,所以,就是在这里创建的线程来处理请求的

     

    \

     

    接下来我们看看Accptor类的run()方法中究竟写了什么:

     

    \

     

     

    \

     

    到这里,我们就创建了acceptor线程和http线程池了。

     

    \

     

    接下来处理另外一个connector:这里用的协议处理器是JkCoyoteHandler,JkCoyoteHandler的start():

     

    \

     

    启动jkMain:

     

    \

     

    最后,在channelSocket的init()方法中启动TP-Monitor和TP-Processor线程池:

     

    \

     

     

    \

     

    此时,我们可以看到TP-Monitor和TP-Processor线程已经启动:

     

    \

     

    所以我们可以知道tomcat容器的启动过程:

    Bootstrap#start()—>Catalina#start()—>StandardServer#start()—>StandardService#start()—>Connector#start()—>Http11Protocol#start()—>Endpoint#init()—>acceptorThread.start()启动请求线程池

    StandardService#start()—>StandardEngine#start()—>ContainerBase#start()—>StandardHost#start()—>ContainerBase#start()—>StandardContext#start()—>ContainerBase#start()(启动守护线程)

    至此,tomcat的初始化全部完成。

     

    \

     

    至此,tomcat服务器已完全启动了。

    启动的时序图如下:

     

    \

     

    TomcatServer处理一个http请求的过程

    1)当来了一个http请求,acceptor线程先判断现在已存在的线程是否足够,若不足够,则创建一个线程来处理请求,足够就使用已存在的;

     

    \

     

     

    \

     

    2)SocketProcessor来处理请求

     

    \

     

    3)Http11ConnectionHandler的process()方法处理:

     

    \

     

    4)Http11Processor的process():

     

    \

     

     

    \

     

    5)CoyoteAdapter的service():

     

    \

     

    6)StandardEngineValve的invoke():

     

    \

     

    7)StandardHostValve的invoke():

     

    \

     

    8)StandardContextValve的invoke():

     

    \

     

    9)StandardWraValve的invoke():

     

    \

     

    总的流程如下:

     

    \
    展开全文
  • 因为SpringBoot 内置了Tomcat容器,所以可以把 web 程序打成 jar 包,直接启动,而且在开发中也不需要像传统Spring项目那样,需要把项目添加到Tomcat中进行启动。不得不说,Springboot确实在方方面面提高了开发效率...

    1. 前言

    因为SpringBoot 内置了Tomcat容器,所以可以把 web 程序打成 jar 包,直接启动,而且在开发中也不需要像传统Spring项目那样,需要把项目添加到Tomcat中进行启动。不得不说,Springboot确实在方方面面提高了开发效率。
    在这里插入图片描述

    2. 从 Main 方法说起

    SpringBoot 项目有一个启动类,启动类里有一个 main 方法用来启动整个应用:
    在这里插入图片描述
    run()方法调用链:

    1. SpringApplication.run(DemoApplication.class, args)
    2. run(new Class<?>[] { primarySource }, args)
    3. new SpringApplication(primarySources).run(args)

    最后跟踪到:SpringApplication.run()方法:
    在这里插入图片描述
    各步骤说明如下:

    1. 设置系统属性『java.awt.headless』,为true则启用headless模式支持;
    2. 通过 SpringFactoriesLoader 检索 META-INF/spring.factories ,找到声明的所有SpringApplicationRunListener的实现类并将其实例化,之后逐个调用其started()方法,广播SpringBoot要开始执行了;
    3. 发布应用开始启动事件;
    4. 初始化参数
    5. 创建并配置当前SpringBoot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile),并遍历调用所有的SpringApplicationRunListener的environmentPrepared()方法,广播Environment准备完毕。
    6. 打印banner;
    7. 创建应用上下文;
    8. 通过SpringFactoriesLoader检索META-INF/spring.factories,获取并实例化异常分析器;
    9. 为ApplicationContext加载environment,之后逐个执行ApplicationContextInitializer的initialize()方法来进一步封装ApplicationContext,并调用所有的SpringApplicationRunListener的contextPrepared()方法,【EventPublishingRunListener只提供了一个空的contextPrepared()方法】,之后初始化IoC容器,并调用SpringApplicationRunListener的contextLoaded()方法,广播ApplicationContext的IoC加载完成,这里就包括通过@EnableAutoConfiguration导入的各种自动配置类;
    10. 刷新上下文;
    11. 再一次刷新上下文,其实是空方法,可能是为了后续扩展;
    12. 发布应用已经启动的事件;
    13. 遍历所有注册的ApplicationRunner和CommandLineRunner,并执行其run()方法(可以实现自己的ApplicationRunner或者CommandLineRunner,来对SpringBoot的启动过程进行扩展);
    14. 应用已经启动完成的监听事件。

    简单的总结下步骤为:1. 配置属性 > 2. 获取监听器,发布应用开始启动事件 > 3. 初始化输入参数 > 4. 配置环境,输出 banner > 5. 创建上下文 > 6. 预处理上下文 > 7. 刷新上下文 > 8. 再刷新上下文 > 9. 发布应用已经启动事件 > 10. 发布应用启动完成事件。

    其实上面这段代码,如果只分析 tomcat ,只需要关注上下文是如何创建的和上下文是如何刷新的,分别对应的方法就是 createApplicationContext() 和 refreshContext(context),接下来看看这两个方法。

    createApplicationContext()方法:
    在这里插入图片描述
    这里就是根据 webApplicationType 来判断创建哪种类型的 Servlet,代码中分别对应着 Web 类型(SERVLET),响应式 Web 类型(REACTIVE),非 Web 类型(default),我们建立的是 Web 类型,所以肯定实例化 DEFAULT_SERVLET_WEB_CONTEXT_CLASS 指定的类,也就是 AnnotationConfigServletWebServerApplicationContext 类,下面用图来说明下这个类的继承关系:
    在这里插入图片描述
    通过类继承关系可知,这个类继承的是 ServletWebServerApplicationContext,而ServletWebServerApplicationContext最后继承了AbstractApplicationContext。

    refreshContext(context)方法:
    在这里插入图片描述
    在这里插入图片描述
    然后调用AbstractApplicationContext的refresh()方法:
    在这里插入图片描述
    其中onRefresh()方法利用模板方法模式,是一个空方法,留给子类实现:
    在这里插入图片描述
    看ServletWebServerApplicationContext中的onRefresh()方法:
    在这里插入图片描述
    顾名思义,createWebServer()就是创建web服务的:
    在这里插入图片描述
    从代码中可知,webServer是从ServletWebServerFactory工厂中获取的,ServletWebServerFactory是一个接口,实现类有:
    在这里插入图片描述
    所以也可以手动指定内嵌容器为其它容器。

    3. 走进 Tomcat

    直接进入TomcatServletWebServerFactory的getWebServer()方法:
    在这里插入图片描述
    该方法主要做了两件事情:

    • 把 Connnctor(我们称之为连接器)对象添加到 Tomcat 中;
    • configureEngine

    跟踪configureEngine()方法:
    在这里插入图片描述
    这个 Engine 其实就是容器Container的子类。

    继续跟踪源码,找到Container接口,看其实现:
    在这里插入图片描述
    其中有4个子接口,分别是Engine,Host,Context,Wrapper。看源码注释可知Engine 是最高级别的容器,其子容器是 Host,Host 的子容器是 Context,Wrapper 是 Context 的子容器,所以这 4 个容器的关系就是父子关系,也就是 Engine>Host>Context>Wrapper。

    再看Tomcat源码:

    //部分源码,其余部分省略。
    public class Tomcat {
    	 //设置连接器
         public void setConnector(Connector connector) {
            Service service = getService();
            boolean found = false;
            for (Connector serviceConnector : service.findConnectors()) {
                if (connector == serviceConnector) {
                    found = true;
                }
            }
            if (!found) {
                service.addConnector(connector);
            }
        }
        //获取service
        public Service getService() {
            return getServer().findServices()[0];
        }
        //设置Host容器
        public void setHost(Host host) {
            Engine engine = getEngine();
            boolean found = false;
            for (Container engineHost : engine.findChildren()) {
                if (engineHost == host) {
                    found = true;
                }
            }
            if (!found) {
                engine.addChild(host);
            }
        }
        //获取Engine容器
        public Engine getEngine() {
            Service service = getServer().findServices()[0];
            if (service.getContainer() != null) {
                return service.getContainer();
            }
            Engine engine = new StandardEngine();
            engine.setName( "Tomcat" );
            engine.setDefaultHost(hostname);
            engine.setRealm(createDefaultRealm());
            service.setContainer(engine);
            return engine;
        }
        //获取server
        public Server getServer() {
    
            if (server != null) {
                return server;
            }
    
            System.setProperty("catalina.useNaming", "false");
    
            server = new StandardServer();
    
            initBaseDir();
    
            // Set configuration source
            ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(new File(basedir), null));
    
            server.setPort( -1 );
    
            Service service = new StandardService();
            service.setName("Tomcat");
            server.addService(service);
            return server;
        }
    
        //添加Context容器
        public Context addContext(Host host, String contextPath, String contextName,
                String dir) {
            silence(host, contextName);
            Context ctx = createContext(host, contextPath);
            ctx.setName(contextName);
            ctx.setPath(contextPath);
            ctx.setDocBase(dir);
            ctx.addLifecycleListener(new FixContextListener());
    
            if (host == null) {
                getHost().addChild(ctx);
            } else {
                host.addChild(ctx);
            }
    
        //添加Wrapper容器
        public static Wrapper addServlet(Context ctx,
                                          String servletName,
                                          Servlet servlet) {
            // will do class for name and set init params
            Wrapper sw = new ExistingStandardWrapper(servlet);
            sw.setName(servletName);
            ctx.addChild(sw);
    
            return sw;
        }
    }
    

    从 Tomcat 的 getServer() 可以知道,Tomcat 的最顶层是 Server,Server 就是 Tomcat 的实例,一个 Tomcat 一个 Server;通过 getEngine() 了解到 Server 下面是 Service,而且是多个,一个 Service 代表部署的一个应用,而且还可以知道,Engine 容器,一个 service 只有一个。

    根据父子关系,看 setHost()源码可以知道,host 容器有多个;同理,从 addContext()源码下知道,Context 也是多个;addServlet()表明 Wrapper 容器也是多个,而且这段代码也暗示了,其实 Wrapper 和 Servlet 是一层意思。另外根据 setConnector 源码可以知道,连接器(Connector)是设置在 service 下的,而且是可以设置多个连接器(Connector)。

    根据上面分析可知:Tomcat 主要包含了 2 个核心组件,连接器(Connector)和容器(Container),用图表示如下:
    在这里插入图片描述
    一个 Tomcat 是一个 Server,一个 Server 下有多个 service,也就是我们部署的多个应用,一个应用下有多个连接器(Connector)和一个容器(Container),容器下有多个子容器,关系用图表示如下:
    在这里插入图片描述
    Engine 下有多个 Host 子容器,Host 下有多个 Context 子容器,Context 下有多个 Wrapper 子容器。

    4. 总结

    SpringBoot 的启动是通过 new SpringApplication()实例来启动的,启动过程主要做如下几件事情:> 1. 配置属性 > 2. 获取监听器,发布应用开始启动事件 > 3. 初始化输入参数 > 4. 配置环境,输出 banner > 5. 创建上下文 > 6. 预处理上下文 > 7. 刷新上下文 > 8. 再刷新上下文 > 9. 发布应用已经启动事件 > 10. 发布应用启动完成事件。

    而启动 Tomcat 就是在第 7 步“刷新上下文”中;Tomcat 的启动主要是初始化 2 个核心组件,连接器(Connector)和容器(Container),一个 Tomcat 实例就是一个 Server,一个 Server 包含多个 Service,也就是多个应用程序,每个 Service 包含多个连接器(Connetor)和一个容器(Container),而容器下又有多个子容器,按照父子关系分别为:Engine,Host,Context,Wrapper,其中除了 Engine 外,其余的容器都是可以有多个。

    展开全文
  • Tomcat启动时加载WEB应用中的后台程序 今天在做项目的时候遇到一个问题。 Tomcat 如何启动时就能运行那些我web应用中后台的处理线程呢...在 Java Web 开发中,Web 应用程序本身没有主动权,他依附于它运行的环境...
  • JAVA程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能。比如说在应用程序用到最大内存的时候,JVM要先去做垃圾回收的动作,释放被占用...
  •  Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录 下的应用。也可以将JSP程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成一个同名的文件夹。一个...
  • Tomcat部署发布JSP应用程序的三种方法   1、直接放到Webapps目录下   Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。也可以将JSP程序打包成一个 ...
  • 1、直接放到Webapps目录下 Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。也可以将JSP程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成...
  • Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。也可以将JSP程序打包成一 个 war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成一个同名的文件夹。一个...
  • 在《深入理解 虚拟机》第二版第九章中作者...其结构如下:上面三个JDK提供的三个默认类加载器:启动类加载器、扩展类加载器和应用程序类加载器。而下面的几个是tomcat自己定义的类加载器,分别用来加载相应目录下的
  •  Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。也可以将JSP程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成一个同名的文件夹。一个...
  • 一个启动速度慢的应用程序不符合这个期望,可能会令用户失望。 这种糟糕的体验可能会导致用户在应用商店中对您的应用进行糟糕的评价,甚至完全放弃您的应用。  如果对原来的类方法修改,那么热启动非常好用;...
  • 1、直接放到Webapps目录下 Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。也可以将JSP程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成...
  • 本文的重点是如何部署,所以暂且先不介绍怎样开发Web应用程序和怎样启动Tomcat服务器,也不考虑使用的什么开发工具,总之在练习本文所说的例子之前,你应该有一个Java Web应用程序。本文假定Web应用程序的根目录为...
  • 本文的重点是如何部署,所以暂且先不介绍怎样开发Web应用程序和怎样启动Tomcat服务器,也不考虑使用的什么开发工具,总之在练习本文所说的例子之前,你应该有一个Java Web应用程序。本文假定Web应用程序的根目录为...
  • 在部署测试服务器时,有的学员问Tomcat作为应用服务器使用,但部署在windows server 2008环境下后,启动应用需要在界面上留下一个CMD窗口,有时可能会被别人误关闭。还不能自启动,遇到这样的问题很头疼,那么接...
  • 上图中启动类加载器,扩展类加载器,应用程序类加载器 jvm自带的类加载器. comm catalina sharedwebapp是tomcat扩展的加载器,他们分别加载/common/*、/server/*、/shared/* WebAppClassLoader负载加载 webapp...
  • 本文的重点是如何部署,所以暂且先不介绍怎样开发Web应用程序和怎样启动Tomcat服务器,也不考虑使用的什么开发工具,总之在练习本文所说的例子之前,你应该有一个Java Web应用程序。本文假定Web应用程序的根目录为...
  • 使用eclipse远程调试tomcat应用程序 背景:程序在本地机上运行没有问题,部署到测试服务器上后出现问题。 在不对代码进行重新部署的前提下如何对服务器上的代码进行debug呢。 答案:让tomcat以jpda试启动 JPDA...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 334
精华内容 133
关键字:

tomcat是如何启动应用程序的