前言
在前几篇文章()中,介绍了 Tomcat 中 Container 及其相关组件,包括 Engine、Host、Context、Wrapper、Pipeline 和 Valve。在这篇文章中分析到了 Service 的 initInternal 和 startInternal 方法,在其中就调用了 Connector 的 init 和 start 方法。Connector 继承自 LifecycleMBeanBase。


1. Connector 构造方法

/**
 * Defaults to using HTTP/1.1 NIO implementation.
 */
public Connector() {
    this("org.apache.coyote.http11.Http11NioProtocol");
}


public Connector(String protocol) {
    boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
            AprLifecycleListener.getUseAprConnector();

    if ("HTTP/1.1".equals(protocol) || protocol == null) {
        if (aprConnector) {
            protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";
        } else {
            protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";
        }
    } else if ("AJP/1.3".equals(protocol)) {
        if (aprConnector) {
            protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";
        } else {
            protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";
        }
    } else {
        protocolHandlerClassName = protocol;
    }

    // Instantiate protocol handler
    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;
    }

    // Default for Connector depends on this system property
    setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
}

在构造方法中,根据配置创建了一个 ProtocolHandler 对象,并把它赋值得 protocolHandler 属性。可以看出,ProtocolHandler 的默认实现类是 Http11NioProtocol。
2. Connector#initInternal 方法

@Override
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() && !AprLifecycleListener.isInstanceCreated()) {
        throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
                getProtocolHandlerClassName()));
    }
    if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
        throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
                getProtocolHandlerClassName()));
    }
    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 {
        protocolHandler.init();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
    }
}

在 initInternal 里,首先创建了一个 CoyoteAdapter 对象,并调用 protocolHandler.setAdapter(adapter),把这个 CoyoteAdapter 对象赋值给 protocolHandler 的 Adapter 类型的 adapter 属性(在 protocolHandler 的实现类的父类 AbstractProtocol 里)。这个 Adapter 对象是 ProtocolHandler 用来处理请求的。
然后对 ProtocolHandler 的属性做了一些设值。
最后调用了 ProtocolHandler#init 方法。
ProtocolHandler 是 Connector 用来处理连接和请求的非常关键的组件。后面会单独分析。
3. Connector#startInternal 方法

@Override
protected void startInternal() throws LifecycleException {

    // Validate settings before starting
    if (getPortWithOffset() < 0) {
        throw new LifecycleException(sm.getString(
                "coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));
    }

    setState(LifecycleState.STARTING);

    try {
        protocolHandler.start();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
    }
}

Connector#startInternal 里最主要的就是调用 ProtocolHandler#init 方法。

小结
本文分析了 Connector 的初始化和启动过程,可以看出,最重要的步骤就是初始化并启动了 ProtocolHandler。


客官
36 声望25 粉丝