Tomcat源碼解析

Tomcat

Tomcat是運(yùn)行在Apache之上的應(yīng)用服務(wù)器,為客戶端提供可以調(diào)用的方法严嗜。Tomcat是一個(gè)Servlet容器(可以認(rèn)為Apache的擴(kuò)展),可獨(dú)立運(yùn)行。

基本結(jié)構(gòu)

Tomcat基本結(jié)構(gòu)

源碼解析

原版Maven Tomcat源碼來自簡(jiǎn)書《maven構(gòu)建tomcat 源碼》

個(gè)人注釋版Tomcat源碼Github Tomcat8.5

Tomcat簡(jiǎn)單類圖

Tomca簡(jiǎn)單類圖

類/接口 作用
Bootstrap 啟動(dòng)類扮叨,封裝了Catalina的基本方法(通過反射)
CatalinaProperties 初始化Tomcat的配置并注冊(cè)到System中
Catalina 啟動(dòng)/關(guān)閉命令行程序
Digester 配置解析器,封裝了XMLReader领迈,通過配置可讀取XML并轉(zhuǎn)化成對(duì)象
Lifecycle 生命周期接口彻磁,擁有init、start狸捅、stop衷蜓、destroy四個(gè)周期API以及添加生命周期監(jiān)聽器LiftcycleListener的API<br />繼承自此接口的類有:Server、Service尘喝、Connector磁浇、Engine、Host朽褪、Context
Server 代表Tomcat服務(wù)器
Service 封裝幾個(gè)連接器和一個(gè)主機(jī)容器Engine置吓,主要用于分組連接器-主機(jī),便于管理
Connector 代表一個(gè)連接器缔赠,負(fù)責(zé)維護(hù)客戶端和服務(wù)器端的連接
Engine 主機(jī)容器衍锚,封裝幾個(gè)主機(jī)以便統(tǒng)一管理
Host 代表一個(gè)虛擬主機(jī)
Context 代表一個(gè)Web應(yīng)用
tomcat生命周期

Bootstrap啟動(dòng)類

Bootstrap擁有main方法,是Tomcat的啟動(dòng)類
Main方法——Bootstrap.main

/**
* 初始化daemon并使用daemon執(zhí)行命令(無參數(shù)默認(rèn)啟動(dòng)嗤堰,有參數(shù)則根據(jù)參數(shù)啟動(dòng)/停止/配置測(cè)試)
* @param args 命令參數(shù)
*/
public static void main(String args[]) {

    //初始化daemon
    if (daemon == null) {
        // 創(chuàng)建一個(gè)Bootstrap對(duì)象戴质,初始化并賦值給daemon
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.init();
        }
        //簡(jiǎn)單打印錯(cuò)誤堆棧,然后重新拋出
        catch (Throwable t) {
            handleThrowable(t);
            t.printStackTrace();
            return;
        }
        daemon = bootstrap;
    } else {
        //有另一個(gè)線程已經(jīng)為daemon賦值踢匣,則讓當(dāng)前線程使用daemon的上下文類加載器
        Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    }

    //使用daemon執(zhí)行命令,默認(rèn)start(調(diào)用Catalina的setAwait告匠、load、start)
    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();
            if (null == daemon.getServer()) {
                System.exit(1);
            }
        } 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);
    }

}

初始化啟動(dòng)器init

public void init() throws Exception {

    //初始化類加載器
    initClassLoaders();

    //為當(dāng)前線程設(shè)置上下文類加載器
    Thread.currentThread().setContextClassLoader(catalinaLoader);
    SecurityClassLoad.securityClassLoad(catalinaLoader);

    
    if (log.isDebugEnabled())
        log.debug("Loading startup class");
    //加載啟動(dòng)類——Catalina符糊,并獲取其實(shí)例
    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
    Object startupInstance = startupClass.getConstructor().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;
    //反射調(diào)用Catalina的setParentClassLoader方法設(shè)置父類加載器為sharedLoader
    Method method =
        startupInstance.getClass().getMethod(methodName, paramTypes);
    method.invoke(startupInstance, paramValues);

    //將實(shí)例化出的Catalina設(shè)置為Catalina守護(hù)
    catalinaDaemon = startupInstance;

}

初始化類加載器initClassLoader

private void initClassLoaders() {
    try {
        //調(diào)用createClassLoader創(chuàng)建common加載器
        commonLoader = createClassLoader("common", null);
        if( commonLoader == null ) {
            // no config file, default to this loader - we might be in a 'single' env.
            commonLoader=this.getClass().getClassLoader();
        }
        //調(diào)用createClassLoader創(chuàng)建catalina加載器和shared加載器
        catalinaLoader = createClassLoader("server", commonLoader);
        sharedLoader = createClassLoader("shared", commonLoader);
    } catch (Throwable t) {
        handleThrowable(t);
        log.error("Class loader creation threw exception", t);
        System.exit(1);
    }
}

創(chuàng)建類加載器createClassLoader

//創(chuàng)建出的類加載器是加載指定路徑j(luò)ar包的UrlClassLoader
private ClassLoader createClassLoader(String name, ClassLoader parent)
    throws Exception {
    //根據(jù)加載器名字從Catalina屬性集獲取屬性值(來自catalina.properties)
    //Debug:value="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
    String value = CatalinaProperties.getProperty(name + ".loader");
    if ((value == null) || (value.equals("")))
        return parent;

    value = replace(value);

    List<Repository> repositories = new ArrayList<>();

    String[] repositoryPaths = getPaths(value);

    //根據(jù)類加載器屬性(jar包地址)生成資源集合
    for (String repository : repositoryPaths) {
        // Check for a JAR URL repository
        try {
            @SuppressWarnings("unused")
            URL url = new URL(repository);
            repositories.add(
                new Repository(repository, RepositoryType.URL));
            continue;
        } catch (MalformedURLException e) {
            // Ignore
        }

        // Local repository
        if (repository.endsWith("*.jar")) {
            repository = repository.substring
                (0, repository.length() - "*.jar".length());
            repositories.add(
                new Repository(repository, RepositoryType.GLOB));
        } else if (repository.endsWith(".jar")) {
            repositories.add(
                new Repository(repository, RepositoryType.JAR));
        } else {
            repositories.add(
                new Repository(repository, RepositoryType.DIR));
        }
    }

    //根據(jù)jar包路徑資源集合創(chuàng)建類加載器——加載指定路徑下jar包的UrlClassLoader
    return ClassLoaderFactory.createClassLoader(repositories, parent);
}

CatalinaProperties配置

CatalinaProperties在加載期獲取Catalina的配置并注冊(cè)到System屬性中
加載Catalina配置

static {
    loadProperties();
}

//加載屬性集并注冊(cè)到System中
private static void loadProperties() {

    //屬性文件輸入流
    InputStream is = null;
    try {
        //屬性文件路徑:系統(tǒng)屬性"catalina.config"
        String configUrl = System.getProperty("catalina.config");
        if (configUrl != null) {
            is = (new URL(configUrl)).openStream();
        }
    } catch (Throwable t) {
        handleThrowable(t);
    }

    //系統(tǒng)屬性為空則 Tomcat項(xiàng)目根目錄\conf\catalina.properties文件
    if (is == null) {
        try {
            File home = new File(Bootstrap.getCatalinaBase());
            File conf = new File(home, "conf");
            File propsFile = new File(conf, "catalina.properties");
            is = new FileInputStream(propsFile);
        } catch (Throwable t) {
            handleThrowable(t);
        }
    }

    //Tomcat項(xiàng)目根目錄\conf\catalina.properties文件不存在則class目錄/org/apache/catalina/startup/catalina.properties文件
    if (is == null) {
        try {
            is = CatalinaProperties.class.getResourceAsStream
                ("/org/apache/catalina/startup/catalina.properties");
        } catch (Throwable t) {
            handleThrowable(t);
        }
    }

    //配置文件不為空凫海,加載配置
    if (is != null) {
        try {
            properties = new Properties();
            properties.load(is);
        } catch (Throwable t) {
            handleThrowable(t);
            log.warn(t);
        } finally {
            try {
                is.close();
            } catch (IOException ioe) {
                log.warn("Could not close catalina.properties", ioe);
            }
        }
    }

    //屬性文件仍舊為空,使用空值對(duì)象取代null(新建Properties對(duì)象)
    if ((is == null)) {
        // Do something
        log.warn("Failed to load catalina.properties");
        // That's fine - we have reasonable defaults.
        properties = new Properties();
    }

    // 最后把屬性全部注冊(cè)進(jìn)System中
    Enumeration<?> enumeration = properties.propertyNames();
    while (enumeration.hasMoreElements()) {
        String name = (String) enumeration.nextElement();
        String value = properties.getProperty(name);
        if (value != null) {
            System.setProperty(name, value);
        }
    }
}

配置文件catalina.properties

#配置訪問權(quán)限(UrlClassLoader在加載類時(shí)會(huì)核對(duì)權(quán)限)男娄,擁有RuntimePermission ("accessClassInPackage."+package)權(quán)限方可訪問
package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.

#配置能夠通過checkPackageDefinition的權(quán)限:RuntimePermission ("defineClassInPackage."+package)
package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,\
org.apache.jasper.,org.apache.naming.,org.apache.tomcat.

#配置類加載器的加載路徑(用于加載Catalina的類加載器)
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"

#配置類加載器的加載路徑(用于加載Server)
server.loader=

#共享型類加載器的加載路徑
shared.loader=

# 配置JarScanner跳過掃描的jar包
# The JARs listed below include:
# - Tomcat Bootstrap JARs
# - Tomcat API JARs
# - Catalina JARs
# - Jasper JARs
# - Tomcat JARs
# - Common non-Tomcat JARs
# - Test JARs (JUnit, Cobertura and dependencies)
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
asm-*.jar,\
aspectj*.jar,\
bootstrap.jar,\
catalina-ant.jar,\
catalina-ha.jar,\
catalina-jmx-remote.jar,\
catalina-storeconfig.jar,\
catalina-tribes.jar,\
catalina-ws.jar,\
catalina.jar,\
cglib-*.jar,\
cobertura-*.jar,\
commons-beanutils*.jar,\
commons-codec*.jar,\
commons-collections*.jar,\
commons-daemon.jar,\
commons-dbcp*.jar,\
commons-digester*.jar,\
commons-fileupload*.jar,\
commons-httpclient*.jar,\
commons-io*.jar,\
commons-lang*.jar,\
commons-logging*.jar,\
commons-math*.jar,\
commons-pool*.jar,\
dom4j-*.jar,\
easymock-*.jar,\
ecj-*.jar,\
el-api.jar,\
geronimo-spec-jaxrpc*.jar,\
h2*.jar,\
hamcrest-*.jar,\
hibernate*.jar,\
httpclient*.jar,\
icu4j-*.jar,\
jasper-el.jar,\
jasper.jar,\
jaspic-api.jar,\
jaxb-*.jar,\
jaxen-*.jar,\
jdom-*.jar,\
jetty-*.jar,\
jmx-tools.jar,\
jmx.jar,\
jsp-api.jar,\
jstl.jar,\
jta*.jar,\
junit-*.jar,\
junit.jar,\
log4j*.jar,\
mail*.jar,\
objenesis-*.jar,\
oraclepki.jar,\
oro-*.jar,\
servlet-api-*.jar,\
servlet-api.jar,\
slf4j*.jar,\
taglibs-standard-spec-*.jar,\
tagsoup-*.jar,\
tomcat-api.jar,\
tomcat-coyote.jar,\
tomcat-dbcp.jar,\
tomcat-i18n-*.jar,\
tomcat-jdbc.jar,\
tomcat-jni.jar,\
tomcat-juli-adapters.jar,\
tomcat-juli.jar,\
tomcat-util-scan.jar,\
tomcat-util.jar,\
tomcat-websocket.jar,\
tools.jar,\
websocket-api.jar,\
wsdl4j*.jar,\
xercesImpl.jar,\
xml-apis.jar,\
xmlParserAPIs-*.jar,\
xmlParserAPIs.jar,\
xom-*.jar

# 需要掃描的jar包(jarsToSkip配置的目錄下可能有需要掃描的jar包)
tomcat.util.scan.StandardJarScanFilter.jarsToScan=\
log4j-taglib*.jar,\
log4j-web*.jar,\
log4javascript*.jar,\
slf4j-taglib*.jar

# 字符串緩存配置
tomcat.util.buf.StringCache.byte.enabled=true
#tomcat.util.buf.StringCache.char.enabled=true
#tomcat.util.buf.StringCache.trainThreshold=500000
#tomcat.util.buf.StringCache.cacheSize=5000

Catalina

Catalina是真正啟動(dòng)Tomcat的類(Bootstrap相當(dāng)于Catalina的對(duì)外代理人)
構(gòu)造函數(shù)

public Catalina() {
    //向Security注冊(cè)訪問權(quán)限
    setSecurityProtection();
    //空方法行贪,提前觸發(fā)ExceptionUtils的加載
    ExceptionUtils.preload();
}
protected void setSecurityProtection(){
    //獲取SecurityConfig單例,SecurityConfig從catalina.properties文件中讀取Security屬性(沒有則使用默認(rèn)值)并設(shè)置到Security中
    SecurityConfig securityConfig = SecurityConfig.newInstance();
    //設(shè)置包定義權(quán)限
    securityConfig.setPackageDefinition();
    //設(shè)置包訪問權(quán)權(quán)限
    securityConfig.setPackageAccess();
}

加載load

public void load() {

    if (loaded) {
        return;
    }
    loaded = true;

    long t1 = System.nanoTime();

    //初始化臨時(shí)目錄
    initDirs();

    // 初始化命名Before digester - it may be needed
    initNaming();

    // 創(chuàng)建并啟動(dòng)配置文件解析器
    Digester digester = createStartDigester();

    InputSource inputSource = null;
    InputStream inputStream = null;
    File file = null;
    try {
        try {
            //獲取配置文件
            file = configFile();
            inputStream = new FileInputStream(file);
            inputSource = new InputSource(file.toURI().toURL().toString());
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("catalina.configFail", file), e);
            }
        }
        if (inputStream == null) {
            try {
                inputStream = getClass().getClassLoader()
                    .getResourceAsStream(getConfigFile());
                inputSource = new InputSource
                    (getClass().getClassLoader()
                     .getResource(getConfigFile()).toString());
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("catalina.configFail",
                                           getConfigFile()), e);
                }
            }
        }

        // 配用配置類加載器目錄/server-embed.xml
        if (inputStream == null) {
            try {
                inputStream = getClass().getClassLoader()
                    .getResourceAsStream("server-embed.xml");
                inputSource = new InputSource
                    (getClass().getClassLoader()
                     .getResource("server-embed.xml").toString());
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("catalina.configFail",
                                           "server-embed.xml"), e);
                }
            }
        }


        if (inputStream == null || inputSource == null) {
            if  (file == null) {
                log.warn(sm.getString("catalina.configFail",
                                      getConfigFile() + "] or [server-embed.xml]"));
            } else {
                log.warn(sm.getString("catalina.configFail",
                                      file.getAbsolutePath()));
                if (file.exists() && !file.canRead()) {
                    log.warn("Permissions incorrect, read permission is not allowed on the file.");
                }
            }
            return;
        }

        try {
            inputSource.setByteStream(inputStream);
            digester.push(this);
            digester.parse(inputSource);
        } catch (SAXParseException spe) {
            log.warn("Catalina.start using " + getConfigFile() + ": " +
                     spe.getMessage());
            return;
        } catch (Exception e) {
            log.warn("Catalina.start using " + getConfigFile() + ": " , e);
            return;
        }
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                // Ignore
            }
        }
    }

    //設(shè)置Server屬性(Catalina模闲、Catalina主目錄建瘫、Catalina根目錄)
    //在Bootstrap的靜態(tài)塊中初始化(先System后用戶路徑/bootstrap.jar)
    getServer().setCatalina(this);
    getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
    getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

    //重定向流
    initStreams();

    // 初始化啟動(dòng)Server
    try {
        getServer().init();
    } catch (LifecycleException e) {
        if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
            throw new java.lang.Error(e);
        } else {
            log.error("Catalina.start", e);
        }
    }

    long t2 = System.nanoTime();
    if(log.isInfoEnabled()) {
        log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
    }
}

啟動(dòng)start

public void start() {

    //Server尚為空——重新加載
    if (getServer() == null) {
        load();
    }

    if (getServer() == null) {
        log.fatal("Cannot start server. Server instance is not configured.");
        return;
    }

    long t1 = System.nanoTime();

    // 啟動(dòng)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");
    }

    // 如果掛了關(guān)閉鉤子——初始化鉤子
    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();
    }
}

停止stop

public void stop() {

    //移除關(guān)閉鉤子(防止被再次觸發(fā))
    try {
        if (useShutdownHook) {
            Runtime.getRuntime().removeShutdownHook(shutdownHook);
            LogManager logManager = LogManager.getLogManager();
            if (logManager instanceof ClassLoaderLogManager) {
                ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                    true);
            }
        }
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
    }

    // 停止并銷毀Server
    try {
        Server s = getServer();
        LifecycleState state = s.getState();
        if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
            && LifecycleState.DESTROYED.compareTo(state) >= 0) {
            // Nothing to do. stop() was already called
        } else {
            s.stop();
            s.destroy();
        }
    } catch (LifecycleException e) {
        log.error("Catalina.stop", e);
    }

}

配置解析器Digester

封裝了XMLReader,通過配置可讀取XML并轉(zhuǎn)化成對(duì)象尸折,用于將服務(wù)器配置(默認(rèn)server.xml)轉(zhuǎn)化為Server對(duì)象
被配置——Catalina的createStartDigester()

protected Digester createStartDigester() {
    long t1=System.currentTimeMillis();
    // Initialize the digester
    Digester digester = new Digester();
    digester.setValidating(false);
    digester.setRulesValidation(true);
    Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
    List<String> objectAttrs = new ArrayList<>();
    objectAttrs.add("className");
    fakeAttributes.put(Object.class, objectAttrs);
    // Ignore attribute added by Eclipse for its internal tracking
    List<String> contextAttrs = new ArrayList<>();
    contextAttrs.add("source");
    fakeAttributes.put(StandardContext.class, contextAttrs);
    digester.setFakeAttributes(fakeAttributes);
    digester.setUseContextClassLoader(true);

    // Configure the actions we will be using
    digester.addObjectCreate("Server",
                             "org.apache.catalina.core.StandardServer",
                             "className");
    digester.addSetProperties("Server");
    digester.addSetNext("Server",
                        "setServer",
                        "org.apache.catalina.Server");

    digester.addObjectCreate("Server/GlobalNamingResources",
                             "org.apache.catalina.deploy.NamingResourcesImpl");
    digester.addSetProperties("Server/GlobalNamingResources");
    digester.addSetNext("Server/GlobalNamingResources",
                        "setGlobalNamingResources",
                        "org.apache.catalina.deploy.NamingResourcesImpl");

    digester.addObjectCreate("Server/Listener",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Listener");
    digester.addSetNext("Server/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");

    digester.addObjectCreate("Server/Service",
                             "org.apache.catalina.core.StandardService",
                             "className");
    digester.addSetProperties("Server/Service");
    digester.addSetNext("Server/Service",
                        "addService",
                        "org.apache.catalina.Service");

    digester.addObjectCreate("Server/Service/Listener",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Listener");
    digester.addSetNext("Server/Service/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");

    //Executor
    digester.addObjectCreate("Server/Service/Executor",
                             "org.apache.catalina.core.StandardThreadExecutor",
                             "className");
    digester.addSetProperties("Server/Service/Executor");

    digester.addSetNext("Server/Service/Executor",
                        "addExecutor",
                        "org.apache.catalina.Executor");


    digester.addRule("Server/Service/Connector",
                     new ConnectorCreateRule());
    digester.addRule("Server/Service/Connector",
                     new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName"}));
    digester.addSetNext("Server/Service/Connector",
                        "addConnector",
                        "org.apache.catalina.connector.Connector");

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
                             "org.apache.tomcat.util.net.SSLHostConfig");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig",
                        "addSslHostConfig",
                        "org.apache.tomcat.util.net.SSLHostConfig");

    digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
                     new CertificateCreateRule());
    digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
                     new SetAllPropertiesRule(new String[]{"type"}));
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
                        "addCertificate",
                        "org.apache.tomcat.util.net.SSLHostConfigCertificate");

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
                             "org.apache.tomcat.util.net.openssl.OpenSSLConf");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
                        "setOpenSslConf",
                        "org.apache.tomcat.util.net.openssl.OpenSSLConf");

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
                             "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
                        "addCmd",
                        "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");

    digester.addObjectCreate("Server/Service/Connector/Listener",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Connector/Listener");
    digester.addSetNext("Server/Service/Connector/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");

    digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
    digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
                        "addUpgradeProtocol",
                        "org.apache.coyote.UpgradeProtocol");

    // Add RuleSets for nested elements
    digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
    digester.addRuleSet(new EngineRuleSet("Server/Service/"));
    digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
    digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
    addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
    digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));

    // When the 'engine' is found, set the parentClassLoader.
    digester.addRule("Server/Service/Engine",
                     new SetParentClassLoaderRule(parentClassLoader));
    addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");

    long t2=System.currentTimeMillis();
    if (log.isDebugEnabled()) {
        log.debug("Digester for server.xml created " + ( t2-t1 ));
    }
    return (digester);

}

解析服務(wù)器配置文件生成Server對(duì)象

public Object parse(InputSource input) throws IOException, SAXException {
    //確認(rèn)是否配置過
    configure();
    //用自身配置配置XMLReader啰脚,然后用XMLReader解析XML文件
    getXMLReader().parse(input);
    return (root);
}

配置文件server.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- Server -->
<Server port="8005" shutdown="SHUTDOWN">

    <!--幾個(gè)生命周期監(jiān)聽器-->
    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

    <!--全局JNDI服務(wù)命名資源集-->
    <GlobalNamingResources>

        <!--用戶數(shù)據(jù)庫(xml數(shù)據(jù)庫),用于讓UserDatabaseRealm校驗(yàn)用戶身份-->
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>

    <!-- Service -->
    <Service name="Catalina">

        <!--Connector的共享執(zhí)行器-->
        <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
                  maxThreads="150" minSpareThreads="4"/>


        <!--Connector連接器,擁有執(zhí)行器橄浓、端口粒梦、協(xié)議、超時(shí)時(shí)限和重定向端口等屬性-->
        <Connector executor="tomcatThreadPool"
                   port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />


        <!--定義一個(gè) 實(shí)現(xiàn)NIO的基于SSL/TLS HTTP/1.1連接的連接器-->
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   maxThreads="150" SSLEnabled="true">
            <SSLHostConfig>
                <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                             type="RSA" />
            </SSLHostConfig>
        </Connector>


        <!-- 定義一個(gè) 協(xié)議為 AJP 1.3 的連接器 -->
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


        <!-- Engine:處理請(qǐng)求荸实,分析請(qǐng)求頭然后傳遞給指定的主機(jī)Host -->
        <Engine name="Catalina" defaultHost="localhost">


            <!-- 用戶身份權(quán)限認(rèn)證 -->
            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                       resourceName="UserDatabase"/>
            </Realm>

            <!--虛擬主機(jī)-->
            <Host name="localhost"  appBase="webapps"
                  unpackWARs="true" autoDeploy="true">

                <!--單例值匀们,保存用戶認(rèn)證信息,此值在多個(gè)Web應(yīng)用下共享-->
                <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                       prefix="localhost_access_log" suffix=".txt"
                       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

            </Host>
        </Engine>
    </Service>
</Server>

生命周期Lifecycle

Lifecycle接口代表組件的生命周期准给,擁有init泄朴、start、stop露氮、destory四個(gè)生命周期方法祖灰,并可添加LifecycleListener生命周期監(jiān)聽器,并定義了若干監(jiān)聽器觸發(fā)事件(初始化前 初始化后 啟動(dòng)前 啟動(dòng) 啟動(dòng)后 停止前 停止 停止后 銷毀前 銷毀后)

骨架類LifecycleBase

簡(jiǎn)單實(shí)現(xiàn)Lifecycle接口——同步生命周期API畔规,確保生命周期狀態(tài)正常變更局扶,并將具體實(shí)現(xiàn)職責(zé)下放到XXXInternal中
構(gòu)造函數(shù)

//未聲明構(gòu)造函數(shù),默認(rèn)構(gòu)造函數(shù)

init

public final synchronized void init() throws LifecycleException {
    //狀態(tài)為New方可初始化
    if (!state.equals(LifecycleState.NEW)) {
        //拋出狀態(tài)異常
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }

    try {
        //狀態(tài)變更——初始化中
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        //初始化具體邏輯
        initInternal();
        //狀態(tài)變更——初始化后
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(
            sm.getString("lifecycleBase.initFail",toString()), t);
    }
}

start

//狀態(tài)為New——現(xiàn)初始化
//狀態(tài)為Failed——停止
//狀態(tài)不為初始化完成或已停止——生命周期異常
public final synchronized void start() throws LifecycleException {
    //狀態(tài)為啟動(dòng)前叁扫、中详民、后——不可啟動(dòng)
    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;
    }

    //狀態(tài)為New——現(xiàn)初始化
    if (state.equals(LifecycleState.NEW)) {
        init();
        //狀態(tài)為Failed——停止
    } else if (state.equals(LifecycleState.FAILED)) {
        stop();
        //狀態(tài)不為初始化完成或已停止——生命周期異常
    } else if (!state.equals(LifecycleState.INITIALIZED) &&
               !state.equals(LifecycleState.STOPPED)) {
        invalidTransition(Lifecycle.BEFORE_START_EVENT);
    }

    try {
        //狀態(tài)變更——啟動(dòng)前
        setStateInternal(LifecycleState.STARTING_PREP, null, false);
        startInternal();
        //狀態(tài)為啟動(dòng)失敗——停止
        if (state.equals(LifecycleState.FAILED)) {
            stop();
            //狀態(tài)不為啟動(dòng)中——生命周期異常
        } else if (!state.equals(LifecycleState.STARTING)) {
            invalidTransition(Lifecycle.AFTER_START_EVENT);
            //狀態(tài)變更——啟動(dòng)后
        } else {
            setStateInternal(LifecycleState.STARTED, null, false);
        }
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
    }
}

stop

//New——直接設(shè)置為停止后
//啟動(dòng)后/啟動(dòng)失敗——執(zhí)行停止
public final synchronized void stop() throws LifecycleException {

    //狀態(tài)為停止前、中陌兑、后——生命周期異常
    if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
        LifecycleState.STOPPED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
        } else if (log.isInfoEnabled()) {
            log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
        }

        return;
    }
    //狀態(tài)為New——變更為已停止
    if (state.equals(LifecycleState.NEW)) {
        state = LifecycleState.STOPPED;
        return;
    }

    //狀態(tài)不為啟動(dòng)后或啟動(dòng)失敗——生命周期異常
    if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
        invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
    }

    try {
        if (state.equals(LifecycleState.FAILED)) {
            //觸發(fā)監(jiān)聽器事件——停止前
            fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        } else {
            setStateInternal(LifecycleSta  te.STOPPING_PREP, null, false);
        }

        stopInternal();

        if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
            invalidTransition(Lifecycle.AFTER_STOP_EVENT);
        }

        setStateInternal(LifecycleState.STOPPED, null, false);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
    } finally {
        if (this instanceof Lifecycle.SingleUse) {
            // Complete stop process first
            setStateInternal(LifecycleState.STOPPED, null, false);
            destroy();
        }
    }
}

destory

//啟動(dòng)失敗——先調(diào)停止,再觸發(fā)銷毀
//New由捎、初始化后兔综、啟動(dòng)后、停止后——觸發(fā)銷毀
public final synchronized void destroy() throws LifecycleException {
    //啟動(dòng)失敗——觸發(fā)停止
    if (LifecycleState.FAILED.equals(state)) {
        try {
            // Triggers clean-up
            stop();
        } catch (LifecycleException e) {
            // Just log. Still want to destroy.
            log.error(sm.getString("lifecycleBase.destroyStopFail", toString()), e);
        }
    }

    //銷毀中或已銷毀——生命周期異常
    if (LifecycleState.DESTROYING.equals(state) ||
        LifecycleState.DESTROYED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
        } else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
            // Rather than have every component that might need to call
            // destroy() check for SingleUse, don't log an info message if
            // multiple calls are made to destroy()
            log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
        }

        return;
    }

    //狀態(tài)不為已停止或啟動(dòng)失敗或New或初始化完成——生命周期異常
    if (!state.equals(LifecycleState.STOPPED) &&
        !state.equals(LifecycleState.FAILED) &&
        !state.equals(LifecycleState.NEW) &&
        !state.equals(LifecycleState.INITIALIZED)) {
        invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
    }

    try {
        setStateInternal(LifecycleState.DESTROYING, null, false);
        destroyInternal();
        setStateInternal(LifecycleState.DESTROYED, null, false);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(
            sm.getString("lifecycleBase.destroyFail",toString()), t);
    }
}

LifecycleMBeanBase

Tomcat構(gòu)件基礎(chǔ)狞玛,Tomcat的構(gòu)件基本都繼承或間接繼承自此類
構(gòu)造函數(shù)

//未聲明構(gòu)造函數(shù)软驰,默認(rèn)構(gòu)造函數(shù)

初始化實(shí)現(xiàn)——initInternal

protected void initInternal() throws LifecycleException {

    //oname為空代表未注冊(cè)到命名服務(wù)——將當(dāng)前對(duì)象注冊(cè)到命名服務(wù)
    if (oname == null) {
        mserver = Registry.getRegistry(null, null).getMBeanServer();

        oname = register(this, getObjectNameKeyProperties());
    }
}

啟動(dòng)實(shí)現(xiàn)——startInternal

//未實(shí)現(xiàn)startInternal()

終止實(shí)現(xiàn)——stopInternal

//未實(shí)現(xiàn)stopInternal()

銷毀實(shí)現(xiàn)——destoryInternal

//未實(shí)現(xiàn)destoryInternal()

組件注冊(cè)器Registry

組件(MBean)注冊(cè)器:提供創(chuàng)建和操作組件以及簡(jiǎn)化組件使用的類,其本身也是一個(gè)組件

實(shí)現(xiàn)了RegistryMBean接口和MBeanRegistration接口
成員變量

意義 變量
日志 Log log
注冊(cè)器集(以web應(yīng)用為鍵) HashMap<Object,Registry> perLoaderRegistries
組件集(以名為鍵) HashMap<String,ManagedBean> descriptors
組件集(以類名為鍵) HashMap<String,ManagedBean> descriptorsByClass
URL集(以名為鍵) HashMap<String,URL> searchedPaths
id所在域集(以域名為鍵) Hashtable<String,Hashtable<String,Integer>> idDomains
id集(以名為鍵) Hashtable<String,int[]> ids

RegistryMBean接口

組件注冊(cè)器的主要接口:提供創(chuàng)建和操作組件以及簡(jiǎn)化組件使用的方法

作用 API
注冊(cè)/取消注冊(cè)組件 register/unRegisterComponent
調(diào)用指定組件列表中所有組件的一個(gè)指定的操作 invoke
獲取能夠更快訪問的ID getId
終止并回到初始狀態(tài) stop

MBeanRegistration接口

組件注冊(cè)的監(jiān)聽器接口心肪,提供注冊(cè)锭亏、取消注冊(cè)觸發(fā)事件的方法

作用 API
注冊(cè)前/后觸發(fā) pre/postRegister
取消注冊(cè)前/后觸發(fā) pre/postDeregister

服務(wù)器Server

Server代表整個(gè)Servlet容器

Server接口繼承自Lifecycle接口,并提供了大量服務(wù)器相關(guān)API
API

類型 作用 API
獲取/設(shè)置 所在Catalina get/setCatalina
Catalina的base路徑 get/setCatalinaBase
Catalina的home路徑 get/setCatalinaHome
全局命名資源 get/setGlobalNamingResource
全局命名上下文 get/setGlobalNamingContext
等待的Shutdown命令字符串 get/setShutdown
地址 get/setAddress
端口號(hào) get/setPort
其他 等待直到Shutdown命令到達(dá) await
查找Service findService(String name)
獲取Service集合 findService
增刪Service add/removeService

實(shí)現(xiàn)類StandardServer

繼承自LifecycleMBeanBase類硬鞍,實(shí)現(xiàn)Server接口
構(gòu)造函數(shù)

public StandardServer() {

    super();

    //初始化全局命名資源集
    globalNamingResources = new NamingResourcesImpl();
    globalNamingResources.setContainer(this);

    //使用了命名服務(wù)——添加命名上下文監(jiān)聽器
    if (isUseNaming()) {
        namingContextListener = new NamingContextListener();
        addLifecycleListener(namingContextListener);
    } else {
        namingContextListener = null;
    }

}

初始化實(shí)現(xiàn)——initInternal

protected void initInternal() throws LifecycleException {

    super.initInternal();

    // JNDI服務(wù)端注冊(cè)字符串緩存服務(wù)(類型為StringCache)
    onameStringCache = register(new StringCache(), "type=StringCache");

    // JNDI服務(wù)端注冊(cè)組件工程服務(wù)(類型為MBeanFactory)
    MBeanFactory factory = new MBeanFactory();
    factory.setContainer(this);
    onameMBeanFactory = register(factory, "type=MBeanFactory");

    // 從JDNI命名資源集中提取數(shù)據(jù)注冊(cè)到JNDI服務(wù)
    globalNamingResources.init();

    // 加載類(來自Catalina.properties慧瘤,在Bootstrap的initClassLoader方法中將jar路徑存放至Url類加載器并將此類加載器存放至Catalina中)
    if (getCatalina() != null) {
        ClassLoader cl = getCatalina().getParentClassLoader();

        while (cl != null && 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() &&
                                f.getName().endsWith(".jar")) {
                                ExtensionValidator.addSystemResource(f);
                            }
                        } catch (URISyntaxException e) {
                            // Ignore
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                }
            }
            cl = cl.getParent();
        }
    }
    // 初始化所有Service
    for (int i = 0; i < services.length; i++) {
        services[i].init();
    }
}

啟動(dòng)實(shí)現(xiàn)——startInternal

protected void startInternal() throws LifecycleException {

    //觸發(fā)監(jiān)聽器——啟動(dòng)事件
    fireLifecycleEvent(CONFIGURE_START_EVENT, null);
    //狀態(tài)切換——啟動(dòng)中
    setState(LifecycleState.STARTING);

    //全局命名資源集啟動(dòng)
    globalNamingResources.start();

    // 啟動(dòng)所有Service
    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            services[i].start();
        }
    }
}

停止實(shí)現(xiàn)——stopInternal

protected void stopInternal() throws LifecycleException {

    //切換狀態(tài)——停止中;觸發(fā)監(jiān)聽器——停止事件
    setState(LifecycleState.STOPPING);
    fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);

    // 停止所有Service
    for (int i = 0; i < services.length; i++) {
        services[i].stop();
    }

    //停止全局命名資源集
    globalNamingResources.stop();
    //停止等待中的線程和socket連接
    stopAwait();
}

銷毀實(shí)現(xiàn)——destoryInternal

protected void destroyInternal() throws LifecycleException {
    // 摧毀所有Service
    for (int i = 0; i < services.length; i++) {
        services[i].destroy();
    }
    //摧毀命名資源集
    globalNamingResources.destroy();

    //取消注冊(cè)組件工廠和字符串緩存
    unregister(onameMBeanFactory);
    unregister(onameStringCache);

    super.destroyInternal();
}

Service

Service是一個(gè)包含多個(gè)連接器Connector和一個(gè)主機(jī)容器Engine的容器固该,以便于:多個(gè)連接器統(tǒng)一為同一個(gè)主機(jī)容器提供請(qǐng)求-響應(yīng)連接锅减。

Service接口繼承自LifeCycle接口,額外提供Service的API伐坏。

類別 作用 API
獲取/設(shè)置 所在服務(wù)器Server get/setServer
名字 get/setServer
類加載器 get/setParentClassLoader
主機(jī)容器Engine get/setContainer
增/刪/查 連接器Connector add/remove/findConnector
連接器共享執(zhí)行器 add/remove/findExecutor

StandardService

Service的默認(rèn)實(shí)現(xiàn)類怔匣,繼承自LifeCycleMBean
構(gòu)造函數(shù)

//未聲明構(gòu)造函數(shù),默認(rèn)構(gòu)造函數(shù)

初始化實(shí)現(xiàn)——initInternal

protected void initInternal() throws LifecycleException {

    super.initInternal();

    //先初始化主機(jī)容器
    if (engine != null) {
        engine.init();
    }

    // 再初始化所有共享執(zhí)行器
    for (Executor executor : findExecutors()) {
        if (executor instanceof JmxEnabled) {
            ((JmxEnabled) executor).setDomain(getDomain());
        }
        executor.init();
    }

    // 初始化監(jiān)聽器
    mapperListener.init();

    // 初始化定義好的連接器(同步)
    synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            try {
                connector.init();
            } catch (Exception e) {
                String message = sm.getString(
                    "standardService.connector.initFailed", connector);
                log.error(message, e);

                if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
                    throw new LifecycleException(message);
            }
        }
    }
}

啟動(dòng)實(shí)現(xiàn)——startInternal

protected void startInternal() throws LifecycleException {

    if(log.isInfoEnabled())
        log.info(sm.getString("standardService.start.name", this.name));
    setState(LifecycleState.STARTING);

    // 同步啟動(dòng)Engine
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }

    //同步啟動(dòng)執(zhí)行器
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }

    //啟動(dòng)映射器監(jiān)聽器
    mapperListener.start();

    // 同步啟動(dòng)所有連接器
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            try {
                // If it has already failed, don't try and start it
                if (connector.getState() != LifecycleState.FAILED) {
                    connector.start();
                }
            } catch (Exception e) {
                log.error(sm.getString(
                    "standardService.connector.startFailed",
                    connector), e);
            }
        }
    }
}

停止實(shí)現(xiàn)——stopInternal

protected void stopInternal() throws LifecycleException {

    // 同步暫停所有連接器
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            try {
                connector.pause();
            } catch (Exception e) {
                log.error(sm.getString(
                    "standardService.connector.pauseFailed",
                    connector), e);
            }
            // Close server socket if bound on start
            // Note: test is in AbstractEndpoint
            connector.getProtocolHandler().closeServerSocketGraceful();
        }
    }

    //狀態(tài)切換
    if(log.isInfoEnabled())
        log.info(sm.getString("standardService.stop.name", this.name));
    setState(LifecycleState.STOPPING);

    // 停止Engine
    if (engine != null) {
        synchronized (engine) {
            engine.stop();
        }
    }

    // 同步停止所有連接器
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            if (!LifecycleState.STARTED.equals(
                connector.getState())) {
                // Connectors only need stopping if they are currently
                // started. They may have failed to start or may have been
                // stopped (e.g. via a JMX call)
                continue;
            }
            try {
                connector.stop();
            } catch (Exception e) {
                log.error(sm.getString(
                    "standardService.connector.stopFailed",
                    connector), e);
            }
        }
    }

    //停止映射器監(jiān)聽器
    if (mapperListener.getState() != LifecycleState.INITIALIZED) {
        mapperListener.stop();
    }

    //同步停止所有執(zhí)行器
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.stop();
        }
    }
}

銷毀實(shí)現(xiàn)——destoryInternal

protected void destroyInternal() throws LifecycleException {
    //摧毀映射器監(jiān)聽器
    mapperListener.destroy();

    // 同步摧毀所有連接器
    synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            try {
                connector.destroy();
            } catch (Exception e) {
                log.error(sm.getString(
                    "standardService.connector.destroyFailed", connector), e);
            }
        }
    }

    // 摧毀所有執(zhí)行器
    for (Executor executor : findExecutors()) {
        executor.destroy();
    }

    //摧毀Engine
    if (engine != null) {
        engine.destroy();
    }

    super.destroyInternal();
}

連接器Connector

Connector維護(hù)客戶端和服務(wù)器端的聯(lián)系桦沉,繼承自LifecycleMBeanBase每瞒,額外提供連接器API

類型 作用 API
獲取/設(shè)置 所在Service get/setService
使用執(zhí)行器的名字 get/setExecutorName
協(xié)議處理器的指定屬性 get/setProperty
協(xié)議處理器的指定屬性(效果同上) get/setAttribute
是否可追溯 get/setAllowTrace
請(qǐng)求的同步時(shí)限 get/setAsyncTimeout
是否允許DNS查找 get/setEnableLookups
最大Cookie數(shù) get/setMaxCookieCount
最大參數(shù)數(shù) get/setMaxParameterCount
Post請(qǐng)求大小限制 get/setMaxPostSize
端口號(hào) get/setPort
協(xié)議 get/setProtocol
協(xié)議執(zhí)行器的類名 get/setProtocolHandlerClassName
代理服務(wù)器名 get/setProxyName
代理端口 get/setProxyPort
重定向端口 get/setRedirectPort
增/刪/查 SSL主機(jī)配置 add/remove/findSslHostConfig
更新協(xié)議 add/remove/findUpgradeProtocol

構(gòu)造函數(shù)

public Connector(String protocol) {
    //設(shè)置協(xié)議
    setProtocol(protocol);

    //實(shí)例化協(xié)議執(zhí)行器
    ProtocolHandler p = null;
    try {
        Class<?> clazz = Class.forName(protocolHandlerClassName);
        p = (ProtocolHandler) clazz.getConstructor().newInstance();
    } catch (Exception e) {
        log.error(sm.getString(
            "coyoteConnector.protocolHandlerInstantiationFailed"), e);
    } finally {
        this.protocolHandler = p;
    }

    //設(shè)置字符集
    if (Globals.STRICT_SERVLET_COMPLIANCE) {
        uriCharset = StandardCharsets.ISO_8859_1;
    } else {
        uriCharset = StandardCharsets.UTF_8;
    }
}

初始化實(shí)現(xiàn)——initInternal

protected void initInternal() throws LifecycleException {

    super.initInternal();

    // 初始化協(xié)議執(zhí)行器的連接適配器
    adapter = new CoyoteAdapter(this);
    protocolHandler.setAdapter(adapter);

    // 確保請(qǐng)求體解析器有效
    if (null == parseBodyMethodsSet) {
        setParseBodyMethods(getParseBodyMethods());
    }

    //協(xié)議解析器需要APR/native庫——生命周期異常
    if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
        throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoApr",
                                                  getProtocolHandlerClassName()));
    }
    //基于JSSE(Java安全socket層)的HTTP協(xié)議執(zhí)行器需要設(shè)置SSL實(shí)現(xiàn)類的名稱
    if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
        protocolHandler instanceof AbstractHttp11JsseProtocol) {
        AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
            (AbstractHttp11JsseProtocol<?>) protocolHandler;
        if (jsseProtocolHandler.isSSLEnabled() &&
            jsseProtocolHandler.getSslImplementationName() == null) {
            // OpenSSL is compatible with the JSSE configuration, so use it if APR is available
            jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
        }
    }

    try {
        //初始化協(xié)議執(zhí)行器
        protocolHandler.init();
    } catch (Exception e) {
        throw new LifecycleException(
            sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
    }
}

啟動(dòng)實(shí)現(xiàn)——startInternal

protected void startInternal() throws LifecycleException {

        // 確認(rèn)端口號(hào)有效
        if (getPort() < 0) {
            throw new LifecycleException(sm.getString(
                    "coyoteConnector.invalidPort", Integer.valueOf(getPort())));
        }

        //切換狀態(tài)
        setState(LifecycleState.STARTING);

        try {
            //啟動(dòng)協(xié)議執(zhí)行器
            protocolHandler.start();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
        }
    }

停止實(shí)現(xiàn)——stopInternal

protected void stopInternal() throws LifecycleException {

    //切換狀態(tài)
    setState(LifecycleState.STOPPING);

    try {
        //停止協(xié)議執(zhí)行器
        protocolHandler.stop();
    } catch (Exception e) {
        throw new LifecycleException(
            sm.getString("coyoteConnector.protocolHandlerStopFailed"), e);
    }
}

銷毀實(shí)現(xiàn)——destoryInternal

protected void destroyInternal() throws LifecycleException {
    try {
        //銷毀協(xié)議執(zhí)行器
        protocolHandler.destroy();
    } catch (Exception e) {
        throw new LifecycleException(
            sm.getString("coyoteConnector.protocolHandlerDestroyFailed"), e);
    }

    //從所在Service中移除自己
    if (getService() != null) {
        getService().removeConnector(this);
    }

    super.destroyInternal();
}

協(xié)議執(zhí)行器ProtocolHandler

ProtocolHandler接口代表單線程的協(xié)議執(zhí)行器金闽,用于維護(hù)流式協(xié)議的連接
實(shí)現(xiàn)類

1570275623815.png

API

類型 作用 API
生命周期 初始化 init
啟動(dòng) start
暫停/恢復(fù) pause/resume
停止 stop
銷毀 destory
查詢 是否需要APR/native庫 isAprRequired
協(xié)議是否支持發(fā)送文件 isSendfileSupported
獲取/設(shè)置 發(fā)起連接的適配器 get/setAdapter
增/查 SSL主機(jī)配置 add/findSslHostConfig
更新協(xié)議 add/findUpgradeProtocol

主機(jī)容器Engine

Engine是包含多個(gè)主機(jī)的容器,它封裝多個(gè)主機(jī)剿骨,以便:

  • 統(tǒng)一攔截到達(dá)他們的請(qǐng)求代芜;
  • 讓他們統(tǒng)一使用同一個(gè)連接器

Engine實(shí)現(xiàn)LifeCycle接口,額外提供Engine的API懦砂。

作用 API
獲取/設(shè)置所在Service get/setService
獲取/設(shè)置默認(rèn)主機(jī) get/setDefaultHost
獲取/設(shè)置JVM路由ID get/setJvmRoute

StandardEngine

Engine的默認(rèn)實(shí)現(xiàn)類蜒犯,繼承自ContainerBase(間接繼承自LifecycleMBeanBase)
構(gòu)造函數(shù)

//創(chuàng)建擁有默認(rèn)屬性的Engine(Jvm路由:系統(tǒng)jvmRoute屬性;后臺(tái)進(jìn)程延遲:10)
public StandardEngine() {

    super();
    pipeline.setBasic(new StandardEngineValve());

    try {
        setJvmRoute(System.getProperty("jvmRoute"));
    } catch(Exception ex) {
        log.warn(sm.getString("standardEngine.jvmRouteFail"));
    }

    backgroundProcessorDelay = 10;

}

初始化實(shí)現(xiàn)——initInternal

protected void initInternal() throws LifecycleException {
    // 確保權(quán)限認(rèn)證Realm存在
    getRealm();
    super.initInternal();
}
public Realm getRealm() {
    Realm configured = super.getRealm();
    //權(quán)限認(rèn)證Realm不存在——返回空值對(duì)象
    if (configured == null) {
        configured = new NullRealm();
        this.setRealm(configured);
    }
    return configured;
}

啟動(dòng)實(shí)現(xiàn)——startInternal

protected synchronized void startInternal() throws LifecycleException {

    if(log.isInfoEnabled())
        log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());

    super.startInternal();
}

停止實(shí)現(xiàn)——stopInternal

//未實(shí)現(xiàn)stopInternal

銷毀實(shí)現(xiàn)——destoryInternal

//未實(shí)現(xiàn)destoryInternal
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末荞膘,一起剝皮案震驚了整個(gè)濱河市罚随,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羽资,老刑警劉巖淘菩,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異屠升,居然都是意外死亡潮改,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門腹暖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汇在,“玉大人,你說我怎么就攤上這事脏答「庋常” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵殖告,是天一觀的道長(zhǎng)阿蝶。 經(jīng)常有香客問我,道長(zhǎng)黄绩,這世上最難降的妖魔是什么羡洁? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮爽丹,結(jié)果婚禮上筑煮,老公的妹妹穿的比我還像新娘。我一直安慰自己习劫,他們只是感情好咆瘟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诽里,像睡著了一般袒餐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天灸眼,我揣著相機(jī)與錄音卧檐,去河邊找鬼。 笑死焰宣,一個(gè)胖子當(dāng)著我的面吹牛霉囚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匕积,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼盈罐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了闪唆?” 一聲冷哼從身側(cè)響起盅粪,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悄蕾,沒想到半個(gè)月后票顾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帆调,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年奠骄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片番刊。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡含鳞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芹务,到底是詐尸還是另有隱情民晒,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布锄禽,位于F島的核電站,受9級(jí)特大地震影響靴姿,放射性物質(zhì)發(fā)生泄漏沃但。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一佛吓、第九天 我趴在偏房一處隱蔽的房頂上張望宵晚。 院中可真熱鬧,春花似錦维雇、人聲如沸淤刃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逸贾。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铝侵,已是汗流浹背灼伤。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咪鲜,地道東北人狐赡。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像疟丙,于是被迫代替她去往敵國(guó)和親颖侄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容