参考资料:
[1]. 深入剖析Tomcat(How Tomcat works)书籍代码下载地址
- 第五章:servlet容器
servlet容器主要分为Engine,Host,Context,Wrapper四种。
上一章讲到连接器会调用servlet容器的invoke方法,实际上调用到容器的管道的invoke方法,管道会依次调用它的各个阀门的invoke方法,最后调用容器的基础阀门。
Wrapper的基础阀门负责载入相关联的servlet类,对请求进行响应。
public class SimpleWrapperValve implements Valve, Contained {
protected Container container;
public void invoke(Request request, Response response,
ValveContext valveContext) throws IOException, ServletException {
SimpleWrapper wrapper = (SimpleWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// Allocate a servlet instance to process this request
try {
servlet = wrapper.allocate();
if (hres != null && hreq != null) {
servlet.service(hreq, hres);
} else {
servlet.service(sreq, sres);
}
} catch (ServletException e) {
}
}
}
Context的基础阀门SimpleContextValve负责找到对应的Wrapper容器,然后调用Wrapper容器的invoke方法。
public class SimpleContextValve implements Valve, Contained {
protected Container container;
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
}
// Disallow any direct access to resources 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();
Context context = (Context) getContainer();
// Select the Wrapper to be used for this 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 this Request
response.setContext(context);
wrapper.invoke(request, response);
}
}
Context中mappers存放着协议和Mapper的映射,Mapper.map负责从servletMappings中找出相对路径对应的Wrapper,servletMappings存放着相对URI和对应的Wrapper的名字,children中存放着Wrapper名字和对应的Wrapper实例。
public Container map(Request request, boolean update) {
// Identify the context-relative URI to be mapped
String contextPath = ((HttpServletRequest) request.getRequest())
.getContextPath();
String requestURI = ((HttpRequest) request).getDecodedRequestURI();
String relativeURI = requestURI.substring(contextPath.length());
// Apply the standard request URI mapping rules from the specification
Wrapper wrapper = null;
String servletPath = relativeURI;
String pathInfo = null;
String name = context.findServletMapping(relativeURI);
if (name != null)
wrapper = (Wrapper) context.findChild(name);
return (wrapper);
}








网友评论