`
韩悠悠
  • 浏览: 839667 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

18,tomcat的主机(host)和引擎

 
阅读更多

如果需要在一个Tomcat部署中部署多个上下文,需要使用一个主机
引擎表示整个Catalina 的Servlet引擎。如果使用的话,它位于容器等级的最高层
可以添加到引擎上的容器包括org.apache.catalina.Host 或者org.apache.catalina.Context。
在一个Tomcat部署中,默认的容器是引擎。

Host相关的StandardHost、StandardHostMapper以及StandardHostValve类。
Host接口
主机是用org.apache.catalina.Host接口表示的。本接口继承了Container接口

public interface Host extends Container { 
	public static final String ADD_ALIAS_EVENT = "addAlias";
	public static final String REMOVE_ALIAS_EVENT = "removeAlias";
	public String getAppBase();
	public void setAppBase(String appBase);
	public boolean getAutoDeploy();
	public void setAutoDeploy(boolean autoDeploy);
	public void addDefaultContext(DefaultContext defaultContext);
	public DefaultContext getDefaultContext();
	public String getName();
	public void setName(String name);
	public void importDefaultContext(Context context);
	public void addAlias(String alias);
	public String[] findAliases();
	public Context map(String uri);
	public void removeAlias(String alias);
}

 

 

StandardHost类
org.apache.catalina.core.StandardHost类是对Host接口的标准实现。
该继承了org.apache.catalina.core.ContainerBase类并实现了Host接口和Deployer接口
跟StandardContext和StandardWrapper类相似,StandardHost类的构造函数在它的流水线中添加一个基本阀门。

public StandardHost() { 
	super(); 
	pipeline.setBasic(new StandardHostValve()); 
}

 

该阀门的类型为org.apache.catalina.core.StandardHostValve。
start方法被调用的时候,StandardHost上面添加两个阀门:ErrorReportValve 和 ErrorDispatcherValve。

The start method of StandardHost
public synchronized void start() throws LifecycleException {
	if ((errorReportValveClass != null) && (!errorReportValveClass.equals(""))) {
		try {
			Valve valve = (Valve) Class.forName(errorReportValveClass).newInstance();
			addValve(valve)
		} catch (Throwable t) {}
	}
	addValve(new ErrorDispatcherValve());
	super.start();
}

 

对于每一个请求,都会调用主机的invoke方法。由于StanardHost类并没有实现invoke方法,
所以会调用它的父类ContainerBase类的invoke方法。该invoke方法会转而调用StandardHost 的基本阀门StandardHostValve的invoke方法。
StandardHostValve的invoke方法调用StandardHost类的map方法获得一个合适的上下文容器来处理请求

//The map method in the StandardHost class
public Context map(String uri) {
	if (uri == null)
		return (null);
	Context context = null; 
	String mapuri = 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) {
		context = (Context) findChild("");
	}
	if (context == null)
		return (null);
	
	return (context);
}

 

StandardHostMapper类
StandardHost的父类ContainerBase使用addDefaultMapper方法创建一个默认映射器。
默认映射器的类型由mapperClass属性指定。这里是ContainerBase的addDefaulstMapper方法:

protected void addDefaultMapper(String mapperClass) {
	if (mapperClass == null)
		return;
	if (mappers.size() >= 1)
		return;
	try {
		Class clazz = Class.forName(mapperClass); 
		Mapper mapper = (Mapper) clazz.newInstance();
		mapper.setProtocol("http");
		addMapper(mapper);
	} catch (Exception e) {}
}

 

StandardHost类的start方法在它的最后调用super.start(),这样保证了创建一个默认的映射器。
StandardHostMapper中最重要的方法是map方法,下面是它的实现:

public Container map(Request request, boolean update) {
	// Has this request already been mapped? 
	if (update && (request.getContext() != null))
		return (request.getContext());
	String uri = ((HttpRequest) request).getDecodedRequestURI();
	Context context = host.map(uri);
	// Update the request (if requested) and return the selected Context 
	if (update) {
		request.setContext(context); 
		if (context != null)
			((HttpRequest) request).setContextPath(context.getPath());
		else
			((HttpRequest) request).setContextPath(null);
	}
	return (context);
}

 

StandardHostValve类
org.apache.catalina.core.StandardHostValve类是StandardHost的基本阀门类型。
当有HTTP请求的时候会调用它的invoke方法:

public void invoke(Request request, Response response, ValveContext valveContext){
	if (!(request.getRequest() instanceof HttpServletRequest) || !(response.getResponse() instanceof HttpServletResponse)) {
		return; 
		// NOTE - Not much else we can do generically }
	}
	StandardHost host = (StandardHost) getContainer();
	Context context = (Context) host.map(request, true); 
	if (context == null) { 
		((HttpServletResponse) response.getResponse()).sendError 
		(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getstring("StandardHost.noContext"));
		return;
	}
	// Bind the context CL to the current thread 
	Thread.currentThread().setContextClassLoader (context.getLoader().getClassLoader());
	// Update the session last access time for our session (if any) 
	HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
	String sessionId = hreq.getRequestedSessionId();
	if (sessionId != null) {
		Manager manager = context.getManager();
		if (manager != null) {
			Session session = manager.findSession(sessionId);
			if ((session != null) && session.isValid())
				session.access();
		}
	}
	// Ask this Context to process this request 
	context.invoke(request, response);
}

 

invoke方法中调用StandardHost的map方法来获得一个合适的上下文。
StandardHost host = (StandardHost) getContainer();
Context context = (Context) host.map(request, true);

Invoke方法解析来得到一个Session对象并调用它的access方法,access方法更新它的最后进入时间,
public void access() {
 this.isNew = false;
 this.lastAccessedTime = this.thisAccessedTime;
 this.thisAccessedTime = System.currentTimeMillis();
}

最后,invoke方法调用上下文容器的invoke方法,让上下文来处理请求。

public final class Bootstrap1 {
	public static void main(String[] args) {
		System.setProperty("catalina.base", System.getProperty("user.dir"));
		Connector connector = new HttpConnector();
		Wrapper wrapper1 = new StandardWrapper(); 
		wrapper1.setName("Primitive"); 
		wrapper1.setServletClass("PrimitiveServlet");
		Wrapper wrapper2 = new StandardWrapper();
		wrapper2.setName("Modern"); 
		wrapper2.setServletClass("ModernServlet"); 
		Context context = new StandardContext();
		context.setPath("/app1"); 
		context.setDocBase("app1"); 
		context.addChild(wrapper1); 
		context.addChild(wrapper2); 
		LifecycleListener listener = new SimpleContextConfig();
		((Lifecycle) context).addLifecycleListener(listener);
		Host host = new StandardHost(); 
		host.addChild(context); 
		host.setName("localhost");
		host.setAppBase("webapps"); 
		Loader loader = new WebappLoader(); 
		context.setLoader(loader);
		// context.addServletMapping(pattern, name);
		context.addServletMapping("/Primitive", "Primitive");
		context.addServletMapping("/Modern", "Modern"); 
		connector.setContainer(host);
		try { 
			connector.initialize(); 
			((Lifecycle) connector).start(); 
			((Lifecycle) host).start(); 
			// make the application wait until we press a key.
			System.in.read(); 
			((Lifecycle) host).stop(); 
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

Engine接口
Engine接口用来表示一个引擎。引擎表示整个Catalina的Servlet引擎。
当你想要支持多个虚拟主机的时候,需要一个引擎

public interface Engine extends Container {
	/** * 
	*	Return the default hostname for this Engine. 
	*/ 
	public String getDefaultHost();

	//Set the default hostname for this Engine.
	public void setDefaultHost(String defaultHost);

	//Retrieve the JvmRouteId for this engine.
	public String getJvmRoute();

	public void setJvmRoute(String jvmRouteId);

	//Return the <code>Service</code> with which we are associated 
	public Service getService();

	public void setService(Service service);

	public void addDefaultContext(DefaultContext defaultContext);

	public DefaultContext getDefaultContext();

	public void importDefaultContext(Context context);
}

 


可以给引擎设置默认主机或者默认上下文。注意引擎也可以跟服务相关联
StandardEngine类
StandardEngine是Engine接口的标准实现,跟StandardContext和StandardHost相比,
StandardEngine类相对较小。初始化的时候,StandardEngine类需要添加一个基本阀门

public StandardEngine() {
	super();
	pipeline.setBasic(new StandardEngineValve()); 
}

 在Container容器的顶层,StandardEngine可以有子容器,它的子容器必须是主机(host)

StandardEngineValve类
StandardEngineValve是StandardEngine的基本阀门

public void invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException {
	if (!(request.getRequest() instanceof HttpServletRequest) || !(response.getResponse() instanceof HttpServletResponse)) {
		return;
	}
	HttpServletRequest hrequest = (HttpServletRequest) request;
	if ("HTTP/1.1".equals(hrequest.getProtocol()) && (hrequest.getServerName() == null)) {
		((HttpServletResponse) response.getResponse()).sendError (HttpServletResponse.SC_BAD_REQUEST, 
		sm.getString("standardEngine.noHostHeader", request.getRequest().getServerName()));
		return;
	}
	// Select the Host to be used for this Request 
	StandardEngine engine = (StandardEngine) getContainer();
	Host host = (Host) engine.map(request, true);
	if (host == null) {
		((HttpServletResponse) response.getResponse()).sendError 
		(HttpServletResponse.SC_BAD_REQUEST, sm.getString("standardEngine.noHost", 
		request.getRequest().getServerName()));
		return;
	}
	// Ask this Host to process this request 
	host.invoke(request, response);
}

 

在验证了请求对象和响应对象之后,invoke方法获得一个Host实例来处理请求。
它得到主机的方法是调用引擎的map方法。一旦获得了一个主机,它的invoke方法将会被调用。

public final class Bootstrap2 { 
	public static void main(String[] args) {
		System.setProperty("catalina.base", System.getProperty("user.dir"));
		Connector connector = new HttpConnector(); 
		Wrapper wrapper1 = new StandardWrapper(); 
		wrapper1.setName("Primitive");
		wrapper1.setServletClass("PrimitiveServlet");
		Wrapper wrapper2 = new StandardWrapper();
		wrapper2.setName("Modern"); 
		wrapper2.setServletClass("ModernServlet");
		Context context = new StandardContext();
		// StandardContext's start method adds a default mapper
		context.setPath("/app1"); 
		context.setDocBase("app1"); 
		context.addChild(wrapper1); 
		context.addChild(wrapper2);
		LifecycleListener listener = new SimpleContextConfig();
		((Lifecycle) context).addLifecycleListener(listener); 
		Host host = new StandardHost(); 
		host.addChild(context);
		host.setName("localhost");
		host.setAppBase("webapps");
		Loader loader = new WebappLoader();
		context.setLoader(loader); 
		// context.addServletMapping(pattern, name); 
		context.addServletMapping("/Primitive", "Primitive"); 
		context.addServletMapping("/Modern", "Modern");
		Engine engine = new StandardEngine();
		engine.addChild(host); 
		engine.setDefaultHost("localhost"); 
		connector.setContainer(engine);
		try { 
			connector.initialize(); 
			((Lifecycle) connector).start();
			((Lifecycle) engine).start(); 
			// make the application wait until we press a key. 
			System.in.read(); 
			((Lifecycle) engine).stop();
		}catch (Exception e) { 
			e.printStackTrace(); 
		}
	}
}

 

分享到:
评论
1 楼 韩悠悠 2012-11-20  

相关推荐

    tomcat engine,host,context的管道处理——pipeline

    在Tomcat的架构中,Engine、Host和Context是核心组件,它们共同构成了一个灵活且可扩展的服务模型。本文将深入探讨这些组件以及与之相关的Pipeline概念。 首先,我们来看“Engine”(引擎)。Engine是Tomcat容器的...

    Tomcat中的Host和Engine级别的servlet容器.docx

    在实际部署中,尽管Tomcat允许不使用Host容器,但在多域名或虚拟主机环境下,使用Host可以更方便地管理和组织Web应用,同时提供更好的灵活性。Engine则作为一个全局容器,负责整个Tomcat实例的请求处理逻辑。 总之...

    tomcat配置虚拟主机

    总结来说,Tomcat配置虚拟主机主要是通过修改Server.xml文件,创建和配置多个&lt;Host&gt;元素,每个元素对应一个独立的主机名和应用路径。这种配置方法使得在同一台服务器上可以托管多个独立的web站点,极大地提高了资源...

    Tomcat5_x中的虚拟主机配置方法.rar_tomcat_虚拟主机

    在`&lt;Engine&gt;`元素内部(通常是名为"Catalina"的引擎),你需要添加一个新的`&lt;Host&gt;`元素来定义虚拟主机。一个基本的`&lt;Host&gt;`配置可能如下: ```xml &lt;Host name="example....

    apache-tomcat-6.0.35和apache-tomcat-6.0.35 src

    - `server.xml`:核心配置文件,定义了服务器实例的各个组件,如Connector(连接器)、Executor(线程池)、Engine(引擎)、Host(主机)和Context(上下文)等。 - `web.xml`:全局的部署描述符,可以定义全局...

    tomcat源码+文档pdf+源码解析

    Catalina包含Context、Host和Engine等层次结构,它们分别对应于Web应用、虚拟主机和整个服务器。 2. **Coyote**:这是Tomcat的连接器组件,用于接收和响应HTTP请求。Coyote处理网络I/O,并将请求转发给Catalina进行...

    tomcat6源码,学习服务引擎

    Tomcat的核心结构基于Catalina组件模型,由一系列可插拔的组件组成,如Engine(引擎)、Host(主机)、Context(上下文)、Wrapper(Servlet容器)和Loader(类加载器)。这些组件相互协作,构成了Tomcat处理HTTP...

    tomcat工作原理深入解析

    本文将深入探讨Tomcat的主要组成部分,包括Server、Service、Connector、Engine、Host和Context,以及它们之间的交互关系。 1. Server(服务器) Server元素代表整个Catalina servlet容器,它是最高级别的组件,...

    Tomcat的结构和运行机制

    ### Tomcat的结构和运行机制 #### 一、Tomcat的大结构 Tomcat是一个流行的开源Java Servlet容器,用于部署和运行Java Web应用程序。其结构设计非常灵活,支持多种配置方式来满足不同应用场景的需求。 ##### 1. ...

    嵌入tomcat

    3. **配置引擎**:创建`Engine`实例,这将作为容器来包含`Host`节点。`Engine`充当整个Web应用的处理器。 4. **设置虚拟主机**:创建`Host`实例,并将其添加到之前创建的`Engine`中。`Host`代表虚拟主机服务,可以...

    tomcat源码

    - **Host**:Host代表虚拟主机,可以配置多个域名指向同一个Tomcat实例。 - **Engine**:Engine是顶级容器,管理所有Host,负责接收并分配请求。 3. **请求处理流程** 当一个HTTP请求到达时,Coyote适配器接收到...

    Tomcat 7 源代码

    5. **上下文(Context)和虚拟主机(Host)**: 在Tomcat中,每个Web应用对应一个Context,而多个Context可以映射到同一个虚拟主机(Host)。源代码展示了Context和Host的配置及管理方式。 6. **类加载机制**: ...

    tomcat 5.59 admin

    【压缩包子文件的文件名称列表】"jakarta-tomcat-5.5.9" 表明这是Jakarta Tomcat 5.5.9的完整安装包,包含了运行Tomcat所需的全部组件,包括Servlet容器、JSP引擎以及admin相关的Web应用和其他配置文件。解压后,你...

    apache-tomcat-7.0.68

    7. **Host Manager App**:这个工具允许管理员管理Tomcat服务器上的虚拟主机,添加、删除和配置虚拟主机。 8. **Web Application Security**:Tomcat 7.0.68 遵循最新的安全规范,如Servlet 3.0和JASPIC 1.1,提供...

    apache-tomcat-8.5.92.tar.gz

    对于开发者而言,Tomcat还提供了丰富的管理工具,如`Manager App`和`Host Manager App`,它们分别用于管理应用部署和虚拟主机设置。这些工具可以通过浏览器访问`http://localhost:8080/manager/html`和`...

    Tomcat6_64位

    4. **日志管理**:Tomcat的日志文件通常位于`logs`目录下,如`catalina.out`记录了服务器的总体输出,而`host-manager`和`manager`应用的日志则分别记录在各自的应用目录下。 5. **安全性**:Tomcat提供了安全管理...

    Tomcat培训学习资料

    Container则负责具体请求的处理,它通常包括一个或多个子容器,如Engine(引擎)、Host(虚拟主机)、Context(Web应用上下文)和Wrapper(Servlet包装器)。此外,Tomcat的组件具有一个共同的特性,即它们都遵循...

    tomcat的内部原理

    深入理解Tomcat的内部原理有助于我们更好地管理和优化Web应用程序的性能。以下是对Tomcat主要组成部分的详细解析: 1. Server(服务器): Server是Catalina(Tomcat的核心组件)的顶级元素,代表着整个Servlet...

    tomcat8源码

    最顶层的Container是Engine,接着是Host(主机),然后是Context(应用上下文),最后是Wrapper(Servlet容器)。 3. **生命周期接口** Tomcat中的组件都遵循生命周期接口,包括初始化、启动、停止和销毁四个阶段...

    java中间件之tomcat

    - **主机(Host)**: 类似于Apache中的虚拟主机,支持基于完全限定域名(FQDN)的虚拟主机配置。 - **上下文(Context)**: 表示Web应用程序本身,配置Web应用的根目录以及其他设置。 4. **被嵌套组件** - **阀门...

Global site tag (gtag.js) - Google Analytics