博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
StandardHost分析-tomcat6.x源码阅读
阅读量:6182 次
发布时间:2019-06-21

本文共 6050 字,大约阅读时间需要 20 分钟。

hot3.png

2013-10-04

StandardHost是什么

StandardHost是StandardHost.Host的标准实现,继承自ContainerBase基容器,具备容器的功能和特征,在tomcat的结构层次图中位于Engine容器内部,是Engine的子容器,是Context的父容器,负责管理多个Context,即webapp。Host是虚拟主机,一个Engine下面可以有多个虚拟主机。虚拟主机主要做的任务就是负责将Engine中传递过来的请求选择一个合适的Context处理,解决的是Context的选择问题,不同Conext之间数据隔离和共享、数据安全问题,负责根据配置文件生成应用程序的Context。

Host

是tomcat中定义的虚拟主机接口,定义了虚拟主机所需要具备的功能,例如应用文件的磁盘路径,Host的的基路径,校验xml配置文件,发布应用。

ContainerBase

Host继承是基容器具备容器的功能,具有父容器引用,管理子容器和容器中的组件,还有后台任务处理线程。

StandardHostValve

是StandHost的basicvalve,在Host容器pipeline valve链的末端,负责为请求信息选择一个合适的Context处理,控制权转移,控制数据流向。

Host中一些重要的属性

  • aliases Host的别名列表
  • aliasesLock 在对aliase操作时需要加锁
  • appBase Host基路径,tomcat会自动扫描路径下面的应用让后启动
  • configClass Host配置文件处理器类
  • contextClass Host的Context实例类,用于生产Context
  • errorReportValveClass 请求错误处理类,例如404,502
  • childClassLoaders 子容器类加载器,主要是Context使用,使用不同的类加载器,起到安全隔离的作用。

map(String)

请求信息到了Host中,需要为请求选择合适的Context处理,这个方法就是完成这个功能,根据uri选择Context。分析请求URI地址,分解URI,根据URI来定位在当前Host下面的Context,并返回Context。采用的匹配策略是最精确URI匹配规则。

/**	 * Return the Context that would be used to process the specified	 * host-relative request URI, if any; otherwise return null.	 * 根据uri选择合适的Context	 * @param uri	 *            Request URI to be mapped	 */	public Context map(String uri) {		if (log.isDebugEnabled())			log.debug("Mapping request URI '" + uri + "'");		if (uri == null)			return (null);		// Match on the longest possible context path prefix		if (log.isTraceEnabled())			log.trace("  Trying the longest context path prefix");		Context context = null;		String mapuri = uri;		//最精确uri匹配原则		while (true) {			context = (Context) findChild(mapuri);			if (context != null)				break;			//定义最后一个 '/'			int slash = mapuri.lastIndexOf('/');			if (slash < 0)				break;			mapuri = mapuri.substring(0, slash);		}		// If no Context matches, select the default Context		if (context == null) {			if (log.isTraceEnabled())				log.trace("  Trying the default context");			//默认Context			context = (Context) findChild("");		}		// Complain if no Context has been selected		if (context == null) {			log.error(sm.getString("standardHost.mappingError", uri));			return (null);		}		// Return the mapped Context (if any)		if (log.isDebugEnabled())			log.debug(" Mapped to context '" + context.getPath() + "'");		return (context);	}

init()

负责初始化Host,主要完成以下几个步骤:

  • 标记已经初始化,注册Host到MBserver
public void init() {		if (initialized)			return;		initialized = true;		// already registered.		if (getParent() == null) {			try {				// Register with the Engine				ObjectName serviceName = new ObjectName(domain + ":type=Engine");				HostConfig deployer = new HostConfig();				addLifecycleListener(deployer);				if (mserver.isRegistered(serviceName)) {					if (log.isDebugEnabled())						log.debug("Registering " + serviceName								+ " with the Engine");					mserver.invoke(serviceName, "addChild",							new Object[] { this },							new String[] { "org.apache.catalina.Container" });				}			} catch (Exception ex) {				log.error("Host registering failed!", ex);			}		}		if (oname == null) {			// not registered in JMX yet - standalone mode			try {				StandardEngine engine = (StandardEngine) parent;				domain = engine.getName();				if (log.isDebugEnabled())					log.debug("Register host " + getName() + " with domain "							+ domain);				oname = new ObjectName(domain + ":type=Host,host="						+ this.getName());				controller = oname;				Registry.getRegistry(null, null).registerComponent(this, oname,						null);			} catch (Throwable t) {				log.error("Host registering failed!", t);			}		}	}

start()

负责启动Host,主要完成以下几个步骤:

  • 判断是否已经启动
  • 判断是否已经初始化
  • 注册realm到Mbserver中
  • 判断errorReportValveClass类,实例化并添加到pipeline中
  • 调用基类启动器
/**	 * Start this host.	 * 	 * @exception LifecycleException	 *                if this component detects a fatal error that prevents it	 *                from being started	 */	public synchronized void start() throws LifecycleException {		if (started) {			return;		}		if (!initialized)			init();		// Look for a realm - that may have been configured earlier.		// If the realm is added after context - it'll set itself.		if (realm == null) {			ObjectName realmName = null;			try {				realmName = new ObjectName(domain + ":type=Realm,host="						+ getName());				if (mserver.isRegistered(realmName)) {					mserver.invoke(realmName, "init", new Object[] {},							new String[] {});				}			} catch (Throwable t) {				log.debug("No realm for this host " + realmName);			}		}		// Set error report valve		if ((errorReportValveClass != null)				&& (!errorReportValveClass.equals(""))) {			try {				boolean found = false;				if (errorReportValveObjectName != null) {					ObjectName[] names = ((StandardPipeline) pipeline)							.getValveObjectNames();					for (int i = 0; !found && i < names.length; i++)						if (errorReportValveObjectName.equals(names[i]))							found = true;				}				if (!found) {					Valve valve = (Valve) Class.forName(errorReportValveClass)							.newInstance();					addValve(valve);					errorReportValveObjectName = ((ValveBase) valve)							.getObjectName();				}			} catch (Throwable t) {				log.error(sm.getString(						"standardHost.invalidErrorReportValveClass",						errorReportValveClass), t);			}		}		if (log.isDebugEnabled()) {			if (xmlValidation)				log.debug(sm.getString("standardHost.validationEnabled"));			else				log.debug(sm.getString("standardHost.validationDisabled"));		}		super.start();	}

stop() 负责停止Host,使用基类中的stop()方法

destroy()

负责销毁Host,清理资源占用,主要有以下几个步骤:

  • 调用基类的destroy()方法
  • 遍历子容器,调用子容器destroy()
public void destroy() throws Exception {		// destroy our child containers, if any		Container children[] = findChildren();		super.destroy();		for (int i = 0; i < children.length; i++) {			if (children[i] instanceof StandardContext)				((StandardContext) children[i]).destroy();		}	}

MemoryLeakTrackingListener

该类的是用来基类Context类加载的,不同的Context可能由不同的类加载器。

Host是tomcat中定义用来管理Context的容器,StandardHost是Host的标准实现,完成对Context的管理,接收父容器Engine传递过来的请求信息,然后根据URI选择合适的Context处理请求,Host还维护在基路径下面的所有的webapp,为他们生成Context。通过类加载的特性来隔离不同Context在应用层面上面的数据安全,不同Context直接不能直接访问。

一直都在迷茫,不知道想要的是什么

转载于:https://my.oschina.net/douglas/blog/166999

你可能感兴趣的文章
Linux mpstat 命令- 报告处理器的相关统计信息
查看>>
阿里云ECS、Redis再次降价 最高降幅35%
查看>>
《Netty in Action》中文正式出版:阿里工程师耗时2年精心翻译(含试读PDF)
查看>>
《游戏机制——高级游戏设计技术》一第 2 章 突现和渐进
查看>>
Maven实战. 3.5使用Archetype生成项目骨架
查看>>
《HTML5移动开发》—— 第1章 学习移动HTML5、CSS3和Java Script API之前的准备工作...
查看>>
Java核心技术卷I基础知识3.5.9 枚举类型
查看>>
深入实践Spring Boot1.6 小结
查看>>
《Ext JS实战》——1.2 需要知道的事项
查看>>
《JUnit实战(第2版)》—第2章2.2节运行参数化测试
查看>>
DARPA 开发用于自然语言处理的深度学习项目
查看>>
Vertica的这些事&lt;七&gt;—— Vertica中实现Oracle中的ws_concat功能
查看>>
【Spark Summit EU 2016】Sparklint:Spark监控,识别与优化利器
查看>>
AppStore提审攻略
查看>>
解读Keras在ImageNet中的应用:详解5种主要的图像识别模型
查看>>
MySQL锁的用法之行级锁
查看>>
自娱小程序--九宫格
查看>>
tr命令学习
查看>>
数据结构实践——B-树的基本操作
查看>>
【Hadoop Summit Tokyo 2016】Apache Storm中的资源感知调度
查看>>