tomcat 源码概念及解析

server.xml是Tomcat服务器的核心配置文件,它定义了Tomcat服务器的运行参数和容器的配置。下面是对server.xml中一些关键标签的解读:
Server:
这是server.xml文件的根元素,它代表了整个Tomcat服务器的实例。
port属性定义了Tomcat的shutdown端口,用于接收关闭服务器的命令。
shutdown属性定义了关闭服务器的命令字符串。
Listener:
这个标签用于定义服务器启动时要加载的监听器,监听器可以执行一些初始化任务,如日志记录、安全管理等。
GlobalNamingResources:
这个标签用于定义全局的JNDI资源,如数据源、用户数据库等。
Service:
Service代表一个服务,它包含一个Connector和一个Engine,用于处理特定的网络连接。
name属性定义了服务的名称。
Connector:
Connector定义了服务的网络连接器,它负责监听特定的端口,接收和处理网络请求。
port属性定义了监听的端口号。

protocol属性定义了连接器使用的协议,如HTTP/1.1、AJP/1.3等。
connectionTimeout属性定义了连接超时时间。
redirectPort属性定义了HTTPS重定向的端口号。
Engine:
Engine是Tomcat容器的顶层组件,它代表了整个服务器的实例。
name属性定义了引擎的名称。
defaultHost属性定义了默认的Host,当请求的域名没有匹配的Host时,将使用默认的Host。
Host:
Host代表一个虚拟主机,它与一个特定的域名或IP地址关联。
name属性定义了虚拟主机的域名或IP地址。
appBase属性定义了Web应用的根目录。
unpackWARs属性定义了是否自动解压WAR文件。
autoDeploy属性定义了是否自动部署Web应用。
Context:
Context代表一个Web应用的上下文,它定义了Web应用的配置和部署信息。
path属性定义了Web应用的上下文路径。
docBase属性定义了Web应用的文档基础目录。

Valve:
Valve代表一个容器阀,它用于处理容器级别的请求,如日志记录、错误处理等。
以上是server.xml中一些关键标签的解读,通过配置这些标签,你可以自定义Tomcat服务器的行为和性能。

添加标签:在标签内添加一个新的标签,为每个虚拟主机添加一个标签。每个标签应该包含以下属性:
name:指定虚拟主机的域名或IP地址。
appBase:指定虚拟主机的Web应用目录。
autoDeploy:指定是否自动部署应用目录下的应用。
deployOnStartup:指定在Tomcat启动时是否部署应用目录下的应用。
deployXML:指定是否使用web.xml文件来部署应用。

在Tomcat服务器中,Engine、Host、Context是三个关键的概念,它们构成了Tomcat的容器层次结构,用于管理和组织Web应用。下面分别解释这三个概念:
Engine(引擎):
Engine是Tomcat容器的顶层,它代表一个虚拟的服务器,可以包含多个Host。在Tomcat中,通常只有一个Engine实例,名为Catalina。
Engine负责处理HTTP请求的分发,它将请求分发给相应的Host进行处理。
Engine还负责管理Tomcat的全局生命周期,包括启动和停止等。
Host(主机):
Host代表一个虚拟主机,它与一个特定的域名或IP地址关联。一个Engine可以包含多个Host,每个Host可以有多个Web应用。
Host负责处理特定域名或IP地址的HTTP请求,它将请求分发给相应的Context进行处理。
Host还负责管理Web应用的生命周期,包括加载、卸载和重启等。
Context(上下文):
Context代表一个Web应用的上下文,它是Web应用的容器,负责加载、管理和运行Web应用。
Context负责处理具体的Web应用的HTTP请求,它管理Servlet、过滤器、监听器等Web组件的生命周期。
Context还负责管理Web应用的配置,包括读取web.xml文件、处理注解等。

在Tomcat的容器层次结构中,Engine、Host和Context之间形成了一个树状结构,从Engine到Host再到Context,每一层都负责更具体的任务。这种层次结构使得Tomcat能够灵活地管理多个Web应用,同时支持虚拟主机和多域名的配置。

org.apache.catalina.startup.Catalina#load{
    ...org.apache.catalina.startup.Catalina#createStartDigester{
        //addObjectCreate、addSetProperties、addSetNext三个方法都是添加rule规则
        ...addObjectCreate->addRule->new ObjectCreateRule{
            ...begin{
                //根据className反射java对象后入栈
                ...digester.push(instance)...
            }...
            ...end{
                //对象出栈,后续操作对象
                digester.pop()...
            }...
        }...

        ...addSetProperties->addRule->new SetPropertiesRule{
            ...begin{
                //栈顶元素赋值,在使用Digester解析XML文档时,它会根据解析规则创建和管理一个对象栈,用于存储解析过程中创建的Java对象。peek方法允许你在不改变栈状态的情况下查看栈顶的对象。
                ...digester.peek()...

                ...IntrospectionUtils.setProperty(top, name, value)...
            }...
        }...
		//Server设置Listener、Service等
        ...addSetNext->addRule->new SetNextRule{
            ...end{
                //同样栈顶元素开始操作
                ...Object child = digester.peek(0);
                Object parent = digester.peek(1)...
                //IntrospectionUtils.callMethod是Apache Commons Lang库中的一个方法,用于通过反射调用Java对象的方法,parent是要调用方法的对象实例
                ...IntrospectionUtils.callMethod1(parent, methodName,
                    child, paramType, digester.getClassLoader())...
            }...
        }....
        ...digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
        //创建Engine对象,设置监听器EngineConfig等
        digester.addRuleSet(new EngineRuleSet("Server/Service/"));
        //创建Host对象,Engine通过方法addChild设置属性Host等
        digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
        //创建Context对象,设置监听器ContextConfig、Host通过方法addChild设置属性Context等
        digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
        addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
        digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"))...
		
        org.apache.catalina.startup.EngineRuleSet#EngineRuleSet{
            addRuleInstances{
                //方法addObjectCreate、addSetProperties、addRule等
                ...digester.addObjectCreate(prefix + "Engine",
                                 "org.apache.catalina.core.StandardEngine",
                                 "className");
        digester.addSetProperties(prefix + "Engine");
        digester.addRule(prefix + "Engine",
                         new LifecycleListenerRule
                         ("org.apache.catalina.startup.EngineConfig",
                          "engineConfigClass"));
        digester.addSetNext(prefix + "Engine",
                            "setContainer",
                            "org.apache.catalina.Engine")...
            }
        }
    }...
//inputStream 此时是 server.xml
	inputSource.setByteStream(inputStream);
	digester.push(this);
	digester.parse->..parse..->scanDocument->..->scanStartElement->emptyElement{
		startElement(element, attributes, augs)->org.apache.tomcat.util.digester.Digester#startElement{
            //执行rule的begin执行对应的方法其中部分如上三种
            ...getRules()...
            ...for rule...
            ...rule.begin...
        }
        endElement(element, augs)->org.apache.tomcat.util.digester.Digester#endElement{
            ...rules = matches.pop()...
            ...rule.body...
            ...rule.end...
        }
    }->scanEndElement{
        ...endElement{
            ...endElement{
                ...rules = matches.pop()...
                ...for rules->rule.body...
                //rule规则里面就有相应的方法其中部分如上三种
                ...for rules->rule.end...    
            }...
        }...
    }
}
//在startInternal这个方法前会setStateInternal->fireLifecycleEvent触发对应状态事件
org.apache.catalina.Lifecycle#start->startInternal->services.start->startInternal->engine.start->startInternal{
    //StandardEngine extends ContainerBase
    ...super.startInternal{
        //对于engin得到的是host,对于host得到的是context。异步启动StandardHost,StandardContext(configureStarthild->call->child.start()),调用org.apache.catalina.util.LifecycleBase#start{...startInternal...}。
        ...Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<>();
        for (int i = 0; i < children.length; i++) {
            results.add(startStopExecutor.submit(new StartChild(children[i])));
        }...
        // Start our thread
        ...threadStart()...
    }...
}

org.apache.catalina.core.StandardHost#startInternal{
    //同上
    ...super.startInternal{
        //得到StandardContext
        ...Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<>();
        for (int i = 0; i < children.length; i++) {
            //会启动context org.apache.catalina.core.StandardContext#startInternal
            results.add(startStopExecutor.submit(new StartChild(children[i])));
        }...
        //触发ContextConfig事件org.apache.catalina.startup.ContextConfig#configureStart->webConfig
        ...fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null)
            // Start our child containers, if not already started
                for (Container child : findChildren()) {
                    if (!child.getState().isAvailable()) {
                        child.start();
                    }
                }...
        ... // Call ServletContainerInitializers如:org.springframework.web.SpringServletContainerInitializer#onStartup
            for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
                initializers.entrySet()) {
                ...entry.getKey().onStartup(entry.getValue(),
                            getServletContext())..
            }...
        //org.springframework.web.context.ContextLoaderListener
        ...listenerStart->listener.contextInitialized...
    }...
}

org.apache.catalina.startup.ContextConfig#webConfig{
    ...configureContext{
        //处理web.xml中的servlet、filter、listen等
        //此处的wrapper为解析xml后的servlet:default,jsp,dispathservlet等
        ...context.addChild(wrapper){
            ...addChildInternal{
                //org.apache.catalina.core.ContainerBase#children
                ///The child Containers belonging to this Container, keyed by name
    //protected final HashMap<String, Container> children = new HashMap<>();
                ...children.put(child.getName(), child)... //default->org.apache.catalina.servlets.DefaultServlet、jsp->org.apache.jasper.servlet.JspServlet、mvc-test(web.xml中配置的servlet-name)->org.springframework.web.servlet.DispatcherServlet
            }...
        }...
    }...
}
posted @ 2024-09-01 14:45  gsluofu  阅读(24)  评论(0编辑  收藏  举报