2013-11-10java
StandardWrapperValve是StandardWrapper容器的BasicValve,tomcat使用容器的BasicValve来控制处理请求,StandardWrapperValve的做用是负责为请求选择Wrapper,调用Servlet处理请求,控制请求处理流程。寄生于StandardWrapper中,StandardWrapperValve做为BasicValve是如何完成便可功能的呢。tomcat
StandardWrapperValve在方法invoke(Request, Response)中完成便可功能,在StandardCOntextValve的invoke(Request, Response)方法中调用。invoke(Request, Response)中作了不少逻辑操做,方法被标记为final,不容许更改方法。app
invoke(Request, Response)
负责选择Wrapper过滤Filter,调用servlet处理请求,在方法中有不少逻辑操做,详细以下:less
/** * Process a Comet event. The main differences here are to not use sendError * (the response is committed), to avoid creating a new filter chain (which * would work but be pointless), and a few very minor tweaks. * * @param request * The servlet request to be processed * @param response * The servlet response to be created * * @exception IOException * if an input/output error occurs, or is thrown by a * subsequently invoked Valve, Filter, or Servlet * @exception ServletException * if a servlet error occurs, or is thrown by a subsequently * invoked Valve, Filter, or Servlet */ public void event(Request request, Response response, CometEvent event) throws IOException, ServletException { // Initialize local variables we may need Throwable throwable = null; // This should be a Request attribute... long t1 = System.currentTimeMillis(); // FIXME: Add a flag to count the total amount of events processed ? // requestCount++; StandardWrapper wrapper = (StandardWrapper) getContainer(); Servlet servlet = null; Context context = (Context) wrapper.getParent(); // Check for the application being marked unavailable boolean unavailable = !context.getAvailable() || wrapper.isUnavailable(); // Allocate a servlet instance to process this request try { if (!unavailable) { servlet = wrapper.allocate(); } } catch (UnavailableException e) { // The response is already committed, so it's not possible to do // anything } 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; } 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); // Get the current (unchanged) filter chain for this request ApplicationFilterChain filterChain = (ApplicationFilterChain) request .getFilterChain(); // Call the filter chain for this request // NOTE: This also calls the servlet's event() method try { String jspFile = wrapper.getJspFile(); if (jspFile != null) request.setAttribute(Globals.JSP_FILE_ATTR, jspFile); else request.removeAttribute(Globals.JSP_FILE_ATTR); if ((servlet != null) && (filterChain != null)) { // Swallow output if needed if (context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); filterChain.doFilterEvent(request.getEvent()); } finally { String log = SystemLogHandler.stopCapture(); if (log != null && log.length() > 0) { context.getLogger().info(log); } } } else { filterChain.doFilterEvent(request.getEvent()); } } 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); // Do not save exception in 'throwable', because we // do not want to do exception(request, response, e) processing } 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); } // Release the filter chain (if any) for this request if (filterChain != null) { filterChain.reuse(); } // Deallocate the allocated servlet instance 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); } } // If this servlet has been marked permanently unavailable, // unload it and release this instance 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; }
以上是invoke(Request,Response)方法的源码,代码中发现有不少的异常处理逻辑,针对不一样的异常处理逻辑,响应给请求的内容页不同。从上面能够看出invoke方法控制了请求的传递过程,在方法并无直接调用servlet的方法,而是将调用servlet中的方法放到FilterChain中。jsp
再坚持this