2013-11-16java
在tomcat中須要解決響應客戶端請求的Socket問題,即接收客戶端的請求,Connector做爲tomcat中的連接器,管理負責監控網絡端口的網絡鏈接器。它是以管理者的身份存在,不涉及具體的網絡接口監聽,只負責管理監聽網絡組件,負責組件的所需資源的調配和組件的運行狀態控制。做爲一個殼,它能管理實現ProtocolHandler接口的網絡監聽組件,能方便替換網絡監聽組件。apache
Connector做爲一個tomcat組件的生命週期中應該經歷這樣一個過程:初始化-啓動-中止-銷燬.做爲Connector,它須要解決一些問題tomcat
監聽網絡端口組件
在帶一個參數的構造器中指定監聽網絡端口組件,傳遞協議版本或者類名,setProtocol(String)方法負責辨別和之人協議監聽網絡端口的組件,在構造器中實例化監控網絡端口組件。網絡
/** * 指定協議類型 * @param protocol * @throws Exception */ public Connector(String protocol) throws Exception { setProtocol(protocol); // Instantiate protocol handler try { Class clazz = Class.forName(protocolHandlerClassName); this.protocolHandler = (ProtocolHandler) clazz.newInstance(); } catch (Exception e) { log.error(sm.getString( "coyoteConnector.protocolHandlerInstantiationFailed", e)); } }
Connector默認的網絡端口監聽組件是org.apache.coyote.http11.Http11Protocol,同時還附加指定一些常量配置。在完成指定組件後,Connector須要完成組件的初始化任務。app
init()
負責完成Connector組件的初始化任務,首先先判斷Connector所依附的Service是不爲空,而後判斷所寄居的容器不爲空,若爲空,findContainer()方法經過JMX的方式來查詢所寄居的容器,同時在方法內調用真正初始化方法initialize()。dom
initialize()
真正負責完成組件的初始化任務。在方法內部主要完成下面幾步:this
/** * Initialize this connector (create ServerSocket here!) * 初始化鏈接器,建立ServerSocket */ public void initialize() throws LifecycleException { if (initialized) { if (log.isInfoEnabled()) log.info(sm.getString("coyoteConnector.alreadyInitialized")); return; } this.initialized = true; if (oname == null && (container instanceof StandardEngine)) { try { // we are loaded directly, via API - and no name was given to us StandardEngine cb = (StandardEngine) container; oname = createObjectName(cb.getName(), "Connector"); Registry.getRegistry(null, null).registerComponent(this, oname, null); controller = oname; } catch (Exception e) { log.error("Error registering connector ", e); } if (log.isDebugEnabled()) log.debug("Creating name for connector " + oname); } // Initializa adapter //初始化適配器 adapter = new CoyoteAdapter(this); //設置協議處理的適配器 protocolHandler.setAdapter(adapter); // Make sure parseBodyMethodsSet has a default if (null == parseBodyMethodsSet) setParseBodyMethods(getParseBodyMethods()); IntrospectionUtils.setProperty(protocolHandler, "jkHome", System.getProperty("catalina.base")); try { protocolHandler.init();//協議處理器初始化 } catch (Exception e) { throw new LifecycleException(sm.getString( "coyoteConnector.protocolHandlerInitializationFailed", e)); } }
從上面能夠看出,初始化是在作資源配置工做.在組件初始化化完成後,就是組件啓動的任務了,start()方法負責這個功能。debug
start() 負責組件的啓動任務,在方法內部作些事件通知和啓動網絡監聽端口組件.code
/** * Begin processing requests via this Connector. * 開始監聽請求 * * @exception LifecycleException * if a fatal startup error occurs */ public void start() throws LifecycleException { if (!initialized) initialize(); // Validate and update our current state if (started) { if (log.isInfoEnabled()) log.info(sm.getString("coyoteConnector.alreadyStarted")); return; } lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; // We can't register earlier - the JMX registration of this happens // in Server.start callback if (this.oname != null) { // We are registred - register the adapter as well. try { Registry.getRegistry(null, null).registerComponent( protocolHandler, createObjectName(this.domain, "ProtocolHandler"), null); } catch (Exception ex) { log.error( sm.getString("coyoteConnector.protocolRegistrationFailed"), ex); } } else { if (log.isInfoEnabled()) log.info(sm.getString("coyoteConnector.cannotRegisterProtocol")); } try { protocolHandler.start();//協議監聽 } catch (Exception e) { String errPrefix = ""; if (this.service != null) { errPrefix += "service.getName(): \"" + this.service.getName() + "\"; "; } throw new LifecycleException(errPrefix + " " + sm.getString( "coyoteConnector.protocolHandlerStartFailed", e)); } if (this.domain != null) { mapperListener.setDomain(domain); // mapperListener.setEngine( service.getContainer().getName() ); mapperListener.init(); try { ObjectName mapperOname = createObjectName(this.domain, "Mapper"); if (log.isDebugEnabled()) log.debug(sm.getString( "coyoteConnector.MapperRegistration", mapperOname)); Registry.getRegistry(null, null).registerComponent(mapper, mapperOname, "Mapper"); } catch (Exception ex) { log.error( sm.getString("coyoteConnector.protocolRegistrationFailed"), ex); } } }
啓動完成後組件監聽網絡端口,對網絡監聽端口組件有暫定監聽的需求和回覆監聽需求,經過pause()
和resume()
完成,方法內部負責調用組件的暫停監聽和恢復監聽方法.組件的中止運行由stop()
完成.orm
stop()
負責組件的中止功能,也即中止網絡監聽端口組件。
public void stop() throws LifecycleException { // Validate and update our current state if (!started) { log.error(sm.getString("coyoteConnector.notStarted")); return; } lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; try { mapperListener.destroy(); Registry.getRegistry(null, null).unregisterComponent( createObjectName(this.domain, "Mapper")); Registry.getRegistry(null, null).unregisterComponent( createObjectName(this.domain, "ProtocolHandler")); } catch (MalformedObjectNameException e) { log.error(sm .getString("coyoteConnector.protocolUnregistrationFailed"), e); } try { protocolHandler.destroy(); } catch (Exception e) { throw new LifecycleException(sm.getString( "coyoteConnector.protocolHandlerDestroyFailed", e)); } }
以上幾步即完成了組件的stop任務,組件的銷燬工做交由destory()完成,所作的工做就是撤銷JMX註冊和Service移除Connector組件
Connector做爲tomcat的鏈接器組件,負責網絡端口監聽組件的管理配置,能管理實現ProtocolHandler接口,在不須要修改代碼的狀況下,方便實現網絡端口監聽組件的替換,對組件管理和代碼維護頗有幫助.
hold on