Connector分析-tomcat6.x源碼閱讀

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

  • 註冊組件到JMX
  • 設置網絡監聽端口組件的適配器(CoyoteAdapter)
  • 反射爲網絡監聽組件設置jkHome
  • 網絡監聽端口組件初始化
/**
	 * 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

  • 判斷組件是否已經初始化和啓動
  • 觸發START_EVENT生命週期事件監聽,標記已經啓動
  • 註冊組件到JMX
  • 啓動網絡監聽端口組件
/**
	 * 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()
負責組件的中止功能,也即中止網絡監聽端口組件。

  • 判斷是否啓動
  • 觸發STOP_EVENT事件,標記沒有啓動狀態
  • 撤銷組件的JMX註冊
  • 調用網絡監聽端口組件的destory()方法
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

相關文章
相關標籤/搜索