StandardContext继承关系:
根据继承关系,我们可以知道,跟之前处理请求的机制基本是一致的。只是standardContext重写了父类的invoke方法:
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Wait if we are reloading
while (getPaused()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
}
}
// Normal request processing
if (swallowOutput) {
try {
SystemLogHandler.startCapture();
super.invoke(request,response);
} finally {
String log =SystemLogHandler.stopCapture();
if (log != null &&log.length() > 0) {
log(log);
}
}
} else {
super.invoke(request, response);
}
}
单它并没有做什么其他过多的逻辑,然后又将操作提交给了父类的invoke方法,那么又再次进入我们之前处理的流程:
1, 调用了ContainerBase中的Invoke方法
2, 进而掉用了valve的invoke方法,而这里实现了valve接口的实现类是StandardContextValve
3, 这个时候将会调用StandardContextValve的invoke方法了
public void invoke(Request request, Responseresponse,
ValveContextvalveContext)
throws IOException, ServletException {
// Validate the request and responseobject types
if (!(request.getRequest() instanceofHttpServletRequest) ||
!(response.getResponse() instanceofHttpServletResponse)) {
return; // NOTE - Not much else we can dogenerically
}
// Disallow any direct access toresources under WEB-INF or META-INF
HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
String contextPath =hreq.getContextPath();
String requestURI = ((HttpRequest)request).getDecodedRequestURI();
String relativeURI =
requestURI.substring(contextPath.length()).toUpperCase();
if(relativeURI.equals("/META-INF") ||
relativeURI.equals("/WEB-INF") ||
relativeURI.startsWith("/META-INF/") ||
relativeURI.startsWith("/WEB-INF/")) {
notFound(requestURI,(HttpServletResponse) response.getResponse());
return;
}
Context context = (Context)getContainer();
// Select the Wrapper to be used forthis Request
Wrapper wrapper = null;
try {
wrapper = (Wrapper)context.map(request, true);
} catch (IllegalArgumentException e) {
badRequest(requestURI,
(HttpServletResponse)response.getResponse());
return;
}
if (wrapper == null) {
notFound(requestURI,(HttpServletResponse) response.getResponse());
return;
}
// Ask this Wrapper to process thisRequest
response.setContext(context);
wrapper.invoke(request, response);
}
根据代码我们可以知道,将会调用StandardContextMapper的map方法来获取对应的wrapper
4, StandardContextMapper的map方法
public Container map(Request request, booleanupdate) {
int debug = context.getDebug();
// Has this request already beenmapped?
if (update &&(request.getWrapper() != null))
return (request.getWrapper());
// Identify the context-relative URI tobe mapped
String contextPath =
((HttpServletRequest)request.getRequest()).getContextPath();
String requestURI = ((HttpRequest)request).getDecodedRequestURI();
String relativeURI =requestURI.substring(contextPath.length());
if (debug >= 1)
context.log("MappingcontextPath='" + contextPath +
"' with requestURI='" +requestURI +
"' andrelativeURI='" + relativeURI + "'");
// Apply the standard request URImapping rules from the specification
Wrapper wrapper = null;
String servletPath = relativeURI;
String pathInfo = null;
String name = null;
// Rule 1 -- Exact Match
if (wrapper == null) {
if (debug >= 2)
context.log(" Trying exact match");
if(!(relativeURI.equals("/")))
name =context.findServletMapping(relativeURI);
if (name != null)
wrapper = (Wrapper)context.findChild(name);
if (wrapper != null) {
servletPath = relativeURI;
pathInfo = null;
}
}
// Rule 2 -- Prefix Match
if (wrapper == null) {
if (debug >= 2)
context.log(" Trying prefix match");
servletPath = relativeURI;
while (true) {
name =context.findServletMapping(servletPath + "/*");
if (name != null)
wrapper = (Wrapper)context.findChild(name);
if (wrapper != null) {
pathInfo =relativeURI.substring(servletPath.length());
if (pathInfo.length() == 0)
pathInfo = null;
break;
}
int slash =servletPath.lastIndexOf('/');
if (slash < 0)
break;
servletPath =servletPath.substring(0, slash);
}
}
// Rule 3 -- Extension Match
if (wrapper == null) {
if (debug >= 2)
context.log(" Trying extension match");
int slash =relativeURI.lastIndexOf('/');
if (slash >= 0) {
String last =relativeURI.substring(slash);
int period =last.lastIndexOf('.');
if (period >= 0) {
String pattern ="*" + last.substring(period);
name =context.findServletMapping(pattern);
if (name != null)
wrapper = (Wrapper)context.findChild(name);
if (wrapper != null) {
servletPath =relativeURI;
pathInfo = null;
}
}
}
}
// Rule 4 -- Default Match
if (wrapper == null) {
if (debug >= 2)
context.log(" Trying default match");
name =context.findServletMapping("/");
if (name != null)
wrapper = (Wrapper)context.findChild(name);
if (wrapper != null) {
servletPath = relativeURI;
pathInfo = null;
}
}
// Update the Request (if requested)and return this Wrapper
if ((debug >= 1) && (wrapper!= null))
context.log(" Mapped to servlet'" + wrapper.getName() +
"' with servletpath '" + servletPath +
"' and path info'" + pathInfo +
"' andupdate=" + update);
if (update) {
request.setWrapper(wrapper);
((HttpRequest)request).setServletPath(servletPath);
((HttpRequest)request).setPathInfo(pathInfo);
}
return (wrapper);
}
我们这里只需要知道根据请求的url逻辑进行匹配获取对应的封装好实现了warpper的StandardWrapper
6,然后调用standardWrapper的invoke方法
StandardContex请求流程图:
standardContext请求关系类图: