前言
在前几篇文章(五、 六 、 七 、 八 、九)中,介绍了 Tomcat 中 Container 及其相关组件,包括 Engine、Host、Context、Wrapper、Pipeline 和 Valve。在这篇文章中分析到了 Service 的 initInternal 和 startInternal 方法,在其中就调用了 Connector 的 init 和 start 方法。Connector 继承自 LifecycleMBeanBase。
/** * 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。