请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pipeline了,如#service()方法中的这句所示:
connector.getContainer().getPipeline().getFirst().invoke(request, response);
这里的Container是Engine,然后得到它的Pipeline对象,然后得到他的第一个Valve,如果没有配置的话第一个Valve就是Basic的了,这里就是org.apache.catalina.core.StandardEngineValve,最后调用了它的#invoke()方法,源代码如下所示:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 获得Host对象 Host host = request.getHost(); if (host == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString( "standardEngine.noHost", request.getServerName())); return; } // 将请求传递给Host host.getPipeline().getFirst().invoke(request, response); }
这个Valve并没做什么实质性的东西,只是将请求继续传递,当然可以定义自己的Valve实现一些特殊的行为。
还是来继续请求的处理过程,和上边Engine的情况类似,请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法,源代码如下所示:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 获得Context对象 Context context = request.getContext(); if (context == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm .getString("standardHost.noContext")); return; } // 如果没有设置Loader,那么设置为context自己的ClassLoader if (context.getLoader() != null) { Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); } // 将请求通过Pipeline给Context context.getPipeline().getFirst().invoke(request, response); if (Globals.STRICT_SERVLET_COMPLIANCE) { request.getSession(false); } // 处理错误页 response.setSuspended(false); Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR); if (t != null) { throwable(request, response, t); } else { status(request, response); } // 恢复ClassLoader Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader()); }
不出意外的,请求下边就到了org.apache.catalina.core.StandardContextValve,源代码如下:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 不允许请求访问META-INF和WEB-INF文件夹下的内容。 MessageBytes requestPathMB = request.getRequestPathMB(); if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/META-INF")) || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) { notFound(response); return; } // 如果系统正在重新载入中,那么暂停请求。 boolean reloaded = false; while (context.getPaused()) { reloaded = true; try { Thread.sleep(1000); } catch (InterruptedException e) { ; } } // 如果正在重载,停止老的WebappClassLoader并创建一个新的 if (reloaded && context.getLoader() != null && context.getLoader().getClassLoader() != null) { Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); } // 获得Wrapper对象 Wrapper wrapper = request.getWrapper(); if (wrapper == null) { notFound(response); return; } else if (wrapper.isUnavailable()) { wrapper = (Wrapper) container.findChild(wrapper.getName()); if (wrapper == null) { notFound(response); return; } } // 获得Listener列表 Object instances[] = context.getApplicationEventListeners(); ServletRequestEvent event = null; if ((instances != null) && (instances.length > 0)) { event = new ServletRequestEvent(((StandardContext) container).getServletContext(), request.getRequest()); for (int i = 0; i < instances.length; i++) { if (instances[i] == null) continue; if (!(instances[i] instanceof ServletRequestListener)) continue; ServletRequestListener listener = (ServletRequestListener) instances[i]; try { // 调用请求初始化事件 listener.requestInitialized(event); } catch (Throwable t) { container.getLogger().error( sm.getString("standardContext.requestListener.requestInit", instances[i].getClass().getName()), t); ServletRequest sreq = request.getRequest(); sreq.setAttribute(Globals.EXCEPTION_ATTR, t); return; } } } // 调用Wrapper的Valve wrapper.getPipeline().getFirst().invoke(request, response); if ((instances != null) && (instances.length > 0)) { for (int i = 0; i < instances.length; i++) { if (instances[i] == null) continue; if (!(instances[i] instanceof ServletRequestListener)) continue; ServletRequestListener listener = (ServletRequestListener) instances[i]; try { // 调用请求结束事件 listener.requestDestroyed(event); } catch (Throwable t) { container.getLogger().error( sm.getString("standardContext.requestListener.requestDestroy", instances[i].getClass().getName()), t); ServletRequest sreq = request.getRequest(); sreq.setAttribute(Globals.EXCEPTION_ATTR, t); } } } }
这个Valve重要的是包括了对Listener的调用,最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。
public final void invoke(Request request, Response response) throws IOException, ServletException { boolean unavailable = false; Throwable throwable = null; long t1 = System.currentTimeMillis(); requestCount++; // 获得Wrapper所关联的对象 StandardWrapper wrapper = (StandardWrapper) getContainer(); // Servlet对象 Servlet servlet = null; // 获得Context对象 Context context = (Context) wrapper.getParent(); if (!context.getAvailable()) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm .getString("standardContext.isUnavailable")); unavailable = true; } if (!unavailable && wrapper.isUnavailable()) { container.getLogger().info( sm.getString("standardWrapper.isUnavailable", wrapper.getName())); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } unavailable = true; } try { if (!unavailable) { // 分配一个Servelt实例 servlet = wrapper.allocate(); } } catch (UnavailableException e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), e); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } } catch (ServletException e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e)); throwable = e; exception(request, response, e); servlet = null; } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), e); throwable = e; exception(request, response, e); servlet = null; } boolean comet = false; if (servlet instanceof CometProcessor && request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE) { comet = true; request.setComet(true); } // 告知Request已经收到 try { response.sendAcknowledgement(); } catch (IOException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().warn( sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e); throwable = e; exception(request, response, e); } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e); throwable = e; exception(request, response, e); servlet = null; } MessageBytes requestPathMB = null; if (request != null) { requestPathMB = request.getRequestPathMB(); } request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR, ApplicationFilterFactory.REQUEST_INTEGER); request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB); // 创建FilterChain ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance(); ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet); request.setComet(false); try { // web.xml中的<jsp-file>标签 String jspFile = wrapper.getJspFile(); if (jspFile != null) request.setAttribute(Globals.JSP_FILE_ATTR, jspFile); else request.removeAttribute(Globals.JSP_FILE_ATTR); // 调用Filter if ((servlet != null) && (filterChain != null)) { if (context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); if (comet) { filterChain.doFilterEvent(request.getEvent()); request.setComet(true); } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } finally { String log = SystemLogHandler.stopCapture(); if (log != null && log.length() > 0) { context.getLogger().info(log); } } } else { if (comet) { request.setComet(true); filterChain.doFilterEvent(request.getEvent()); } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } } request.removeAttribute(Globals.JSP_FILE_ATTR); } catch (ClientAbortException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); throwable = e; exception(request, response, e); } catch (IOException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); throwable = e; exception(request, response, e); } catch (UnavailableException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); wrapper.unavailable(e); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } } catch (ServletException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); Throwable rootCause = StandardWrapper.getRootCause(e); if (!(rootCause instanceof ClientAbortException)) { container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), rootCause); } throwable = e; exception(request, response, e); } catch (Throwable e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); throwable = e; exception(request, response, e); } if (filterChain != null) { if (request.isComet()) { filterChain.reuse(); } else { filterChain.release(); } } // 释放Servlet对象 try { if (servlet != null) { wrapper.deallocate(servlet); } } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.deallocateException", wrapper.getName()), e); if (throwable == null) { throwable = e; exception(request, response, e); } } try { if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) { wrapper.unload(); } } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.unloadException", wrapper.getName()), e); if (throwable == null) { throwable = e; exception(request, response, e); } } long t2 = System.currentTimeMillis(); long time = t2 - t1; processingTime += time; if (time > maxTime) maxTime = time; if (time < minTime) minTime = time; }
这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());),具体的还要进入方法内部去仔细看一下。comet方式以后再详细看。