tomcat 原理分析

1.版本选择

1.1.SpringMVC版本为3.2.4;
1.2.Tomcat的版本为8.0.47;
1.3.servlet-api的版本为3.1.0;

2.Tomcat的基本原理

2.1.调用在Bootstrap中的主函数main()程序入口调用自身的start()方法,在start()方法中实例化org.apache.catalina.startup.Catalina类调用其start()方法,在Catalina的start()中调用load()载入tomcat文件夹目录下conf文件夹下的server.xml并创建Server类,然后调用Server的start()方法,到这里我们的tomcat就运行起来了.
2.2.Server类代表整个Tomcat服务器,这里有必要介绍一下为什么Tomcat叫Servlet容器,在Tomcat中包含四个容器,分别为Engine,Host,Context,Wrapper.Engine是Host的父容器,依次类推.四者都继承自Container接口.一般在Tomcat中一个Engine实例中包含一个Host实例,一个Host实例中包含一个Context实例,一个Context代表一个WEB程序并包含多个Wrapper实例,一个Wrapper代表一个Servlet类.
2.3.一次请求的大题流程是这样的,首先由Connector获取到Http请求,封装ServletRequest和ServletResponse对象并派发给Context管道中的所有Valve,执行完所有Valve后执行基础Valve根据请求的url映射到对应的Wrapper,然后调用个Wrapper管道中的所有Valve,最后调用基础Valve在如这个Wrapper类所封装的Servlet,实例化后调用器Service方法对用户的请求进行处理,最后将结果负载在response中返回给用户.

3.tomcat运行原理得源码分析

public static void main(String args[])
    {
        if (daemon == null)
        {
            // Don't set daemon until init() has completed
            Bootstrap bootstrap = new Bootstrap();
            try
            {
                bootstrap.init();
            } catch (Throwable t)
            {
                handleThrowable(t);
                t.printStackTrace();
                return;
            }
            daemon = bootstrap;
        } else
        {
            // When running as a service the call to stop will be on a new
            // thread so make sure the correct class loader is used to prevent
            // a range of class not found exceptions.
            Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
        }
        try
        {
            String command = "start";
            if (args.length > 0)
            {
                command = args[args.length - 1];
            }

            if (command.equals("startd"))
            {
                args[args.length - 1] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd"))
            {
                args[args.length - 1] = "stop";
                daemon.stop();
            } else if (command.equals("start"))
            {
                // 在这里读取命令行参数,然后启动。
                daemon.setAwait(true);
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stop"))
            {
                daemon.stopServer(args);
            } else if (command.equals("configtest"))
            {
                daemon.load(args);
                if (null == daemon.getServer())
                {
                    System.exit(1);
                }
                System.exit(0);
            } else
            {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t)
        {
            // Unwrap the Exception for clearer error reporting
            if (t instanceof InvocationTargetException && t.getCause() != null)
            {
                t = t.getCause();
            }
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }
    }

第一次启动是会调用内部生成的Bootstrap类,调用start方法。

 public void start() throws Exception
    {
        if (catalinaDaemon == null)
            init();
        Method method = catalinaDaemon.getClass().getMethod("start", (Class[]) null);
        method.invoke(catalinaDaemon, (Object[]) null);
    }

在init方法中实例化Catalinna类然后通过反射调用其start方法。

 public void init() throws Exception
    {
        initClassLoaders();
        Thread.currentThread().setContextClassLoader(catalinaLoader);
        SecurityClassLoad.securityClassLoad(catalinaLoader);
        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.newInstance();
        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);
        catalinaDaemon = startupInstance;
    }

在start()中调用load()方法载入了Server类,然后调用了其start()方法启动了Tomcat.

 public void start()
    {
        if (getServer() == null)
        {
            load();
        }
        if (getServer() == null)
        {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }
        long t1 = System.nanoTime();
        // Start the new server
        try
        {
            getServer().start();
        } catch (LifecycleException e)
        {
            log.fatal(sm.getString("catalina.serverStartFail"), e);
            try
            {
                getServer().destroy();
            } catch (LifecycleException e1)
            {
                log.debug("destroy() failed for failed Server ", e1);
            }
            return;
        }
        long t2 = System.nanoTime();
        if (log.isInfoEnabled())
        {
            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
        }
        // Register shutdown hook
        if (useShutdownHook)
        {
            if (shutdownHook == null)
            {
                shutdownHook = new CatalinaShutdownHook();
            }
            Runtime.getRuntime().addShutdownHook(shutdownHook);
            // If JULI is being used, disable JULI's shutdown hook since
            // shutdown hooks run in parallel and log messages may be lost
            // if JULI's hook completes before the CatalinaShutdownHook()
            LogManager logManager = LogManager.getLogManager();
            if (logManager instanceof ClassLoaderLogManager)
            {
                ((ClassLoaderLogManager) logManager).setUseShutdownHook(false);
            }
        }
        if (await)
        {
            await();
            stop();
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。