连接器会把请求转发给下游的容器来处理,而engine容器就是下游容器体系中的顶层容器。其主要职责是根据请求的url来匹配合适的host容器。
engine默认实现是standardEngine类:
public class StandardEngine
extends ContainerBase
implements Engine {
在构造方法中设置了该容器的basic valve:
public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
}
容器的invoke方法是由containterBase类提供的,最终就会调用valve的invoke方法:
/**
* Select the appropriate child Host to process this request,
* based on the requested server name. If no matching Host can
* be found, return an appropriate HTTP error.
*
* @param request Request to be processed
* @param response Response to be produced
* @param valveContext Valve context used to forward to the next Valve
*
* @exception IOException if an input/output error occurred
* @exception ServletException if a servlet error occurred
*/
public void invoke(Request request, Response response,
ValveContext valveContext)
throws IOException, ServletException {
// Validate the request and response object types
if (!(request.getRequest() instanceof HttpServletRequest) ||
!(response.getResponse() instanceof HttpServletResponse)) {
return; // NOTE - Not much else we can do generically
}
// Validate that any HTTP/1.1 request included a host header
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);
}
这里主要是根据请求url来map一个host,最后交给host处理,调用host的invoke方法。看下map方法,map方法由StandardEngineMapper实现,在baseContainer的start里设置:
public synchronized void start() throws LifecycleException {
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("containerBase.alreadyStarted", logName()));
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
addDefaultMapper(this.mapperClass);
map方法:
public Container map(Request request, boolean update) {
int debug = engine.getDebug();
// Extract the requested server name
String server = request.getRequest().getServerName();
if (server == null) {
server = engine.getDefaultHost();
if (update)
request.setServerName(server);
}
if (server == null)
return (null);
server = server.toLowerCase();
if (debug >= 1)
engine.log("Mapping server name '" + server + "'");
// Find the matching child Host directly
if (debug >= 2)
engine.log(" Trying a direct match");
Host host = (Host) engine.findChild(server);
// Find a matching Host by alias. FIXME - Optimize this!
if (host == null) {
if (debug >= 2)
engine.log(" Trying an alias match");
Container children[] = engine.findChildren();
for (int i = 0; i < children.length; i++) {
String aliases[] = ((Host) children[i]).findAliases();
for (int j = 0; j < aliases.length; j++) {
if (server.equals(aliases[j])) {
host = (Host) children[i];
break;
}
}
if (host != null)
break;
}
}
// Trying the "default" host if any
if (host == null) {
if (debug >= 2)
engine.log(" Trying the default host");
host = (Host) engine.findChild(engine.getDefaultHost());
}
// Update the Request if requested, and return the selected Host
; // No update to the Request is required
return (host);
}
engine容器会用一个map存所有的子容器:
/**
* The child Containers belonging to this Container, keyed by name.
*/
protected HashMap children = new HashMap();
map方法就是从子容器里拿一个host。
具体有哪些host是由server.xml文件定义。