Tomcat的容器中,有着4个层次的Servlet容器,这4个类型的容器一般情况下是从属的关系.其中顶层的容器为Engine.这个Engine是Tomcat的整个Servlet引擎.它的子容器是Host,默认情况下Tomcat会有一个Engine,它所对应的阀是StandardEngineValve
首先,我们可以回头看下server.xml的配置.
<Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine>
从配置中可以知道Service节点除了定义Connector,还定义了Engine,它里面还有一个Host.也就是说StandardService初始化的时候,就构造了Servlet引擎StandardEngine等一系列的容器层次.我们就看看Engine的构造方法.
public StandardEngine() { super(); pipeline.setBasic(new StandardEngineValve()); /* Set the jmvRoute using the system property jvmRoute */ try { setJvmRoute(System.getProperty("jvmRoute")); } catch(Exception ex) { log.warn(sm.getString("standardEngine.jvmRouteFail")); } // By default, the engine will hold the reloading thread backgroundProcessorDelay = 10; }
StandardEngine继承自ContainerBase自然也就有了pipeline对象和invoke方法.构造函数中设置的基础阀是StandardEngineValve.它是Engine特有的.
public final void invoke(Request request, Response response) throws IOException, ServletException { // Select the Host to be used for this Request Host host = request.getHost(); if (host == null) { response.sendError (HttpServletResponse.SC_BAD_REQUEST, sm.getString("standardEngine.noHost", request.getServerName())); return; } if (request.isAsyncSupported()) { request.setAsyncSupported(host.getPipeline().isAsyncSupported()); } // Ask this Host to process this request host.getPipeline().getFirst().invoke(request, response); }
上述代码是StandardEngineValve的invoke方法,从中我们可以知道它的作用只是把调用转发给了它的子容器Host,也就是他只起到了一个路由的作用.真正处理请求的还是在它的下级容器.