Tomcat源码分析(四)--容器处理链接之责任链模式(二)

2014-11-24 08:41:39 · 作者: · 浏览: 5
就能调用基础阀的invoke了,当basic.invoke(request, response, this);进入基础阀StandardEngineva lve,看基础阀StandardEngineva lve的invoke方法:
[java]
public void invoke(Request request, Response response,
ValveContext valveContext)
throws IOException, ServletException {
...........................

// Ask this Host to process this request
host.invoke(request, response);

}

这里省略了很多代码,主要是为了更加理解调用逻辑,在StandardEngine的基础阀StandardEngineva lve里,调用了子容器invoke方法(这里子容器就是StandardHost),还记得一开始connector.invoke(request, response)(即StandardEngine的invoke方法)现在顺利的传递到子容器StandardHost的invoke方法,变成了StandardHost.invoke(request, response)。由此可以猜测StandardHost也会传递给它的子容器,最后传递到最小的容器StandardWrapper的invoke方法,然后调用StandardWrapper的基础阀StandardWrapperValue的invoke方法,由于StandardWrapper是最小的容器了,不能再传递到其他容器的invoke方法了,那它的invoke方法做了什么?主要做了两件事, 1:创建一个过滤器链并 2:分配一个servlet或者jsp,主要代码如下:
[java]
StandardWrapperValue的invoke方法
servlet = wrapper.allocate(); //分配一个servlet
....................................................................
// Create the filter chain for this request
ApplicationFilterChain filterChain =
createFilterChain(request, servlet);
.........................................................
String jspFile = wrapper.getJspFile();//分配一个jsp
if (jspFile != null)
sreq.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
else
sreq.removeAttribute(Globals.JSP_FILE_ATTR);
if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(sreq, sres);//调用过滤器链处理请求,sreq和sres是request和response的包装类,在这里面会调用servlet的services方法

}

这里先不关注jsp,只关注一下servlet,通过servlet = wrapper.allocate(); 进入StandardWrapper的allocate方法,allocate主要就是调用了loadServlet方法,在loadServlet方法类用tomcat自己的类加载器实例化了一个servlet对象,并调用了该servlet的init和service方法:www.2cto.com
[java]
StandardWrapper的loadServlet方法(这里省略了很多其他的代码)
Servlet servlet = null;
String actualClass = servletClass;//servlet的字节码字符串
Loader loader = getLoader();
ClassLoader classLoader = loader.getClassLoader();//得到类加载器
Class classClass = null;
if (classLoader != null) {
System.out.println("Using classLoader.loadClass");
classClass = classLoader.loadClass(actualClass);//通过类加载器实例化servlet
} else {
System.out.println("Using forName");
classClass = Class.forName(actualClass);//通过反射实例化servlet
}
servlet = (Servlet) classClass.newInstance();//实例化servlet
servlet.init(facade);//调用servlet的init
if ((loadOnStartup > 0) && (jspFile != null)) {
// Invoking jspInit
HttpRequestBase req = new HttpRequestBase();
HttpResponseBase res = new HttpResponseBase();
req.setServletPath(jspFile);
req.setQueryString("jsp_precompile=true");
servlet.service(req, res);
};//调用jsp的service方法,jsp会被编译成servlet,所以也会有service方法

至此已经把请求传递到servlet的service(或者jsp的service)方法,整个处理请求到这里就结束了,剩下的就是返回客户端了。这里提出几个问题。1:那么多的servlet,tomcat是怎么知道要请求