Tomcat请求处理(五) -- 请求在容器间的流动

请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pipeline了,如#service()方法中的这句所示:

connector.getContainer().getPipeline().getFirst().invoke(request, response);

这里的Container是Engine,然后得到它的Pipeline对象,然后得到他的第一个Valve,如果没有配置的话第一个Valve就是Basic的了,这里就是org.apache.catalina.core.StandardEngineValve,最后调用了它的#invoke()方法,源代码如下所示:

Java代码 Tomcat请求处理(五) -- 请求在容器间的流动 - guoyang1982 - 游龙

  1. public final void invoke(Request request, Response response) throws IOException,   
  2.         ServletException {   
  3.   
  4.     // 获得Host对象   
  5.     Host host = request.getHost();   
  6.     if (host == null) {   
  7.         response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString(   
  8.                 "standardEngine.noHost", request.getServerName()));   
  9.         return;   
  10.     }   
  11.   
  12.     // 将请求传递给Host   
  13.     host.getPipeline().getFirst().invoke(request, response);   
  14.   
  15. }  

这个Valve并没做什么实质性的东西,只是将请求继续传递,当然可以定义自己的Valve实现一些特殊的行为。

还是来继续请求的处理过程,和上边Engine的情况类似,请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法,源代码如下所示:

Java代码 Tomcat请求处理(五) -- 请求在容器间的流动 - guoyang1982 - 游龙

  1. public final void invoke(Request request, Response response) throws IOException,   
  2.         ServletException {   
  3.   
  4.     // 获得Context对象   
  5.     Context context = request.getContext();   
  6.     if (context == null) {   
  7.         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm   
  8.                 .getString("standardHost.noContext"));   
  9.         return;   
  10.     }   
  11.   
  12.     // 如果没有设置Loader,那么设置为context自己的ClassLoader   
  13.     if (context.getLoader() != null) {   
  14.         Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());   
  15.     }   
  16.   
  17.     // 将请求通过Pipeline给Context   
  18.     context.getPipeline().getFirst().invoke(request, response);   
  19.   
  20.     if (Globals.STRICT_SERVLET_COMPLIANCE) {   
  21.         request.getSession(false);   
  22.     }   
  23.   
  24.     // 处理错误页   
  25.     response.setSuspended(false);   
  26.   
  27.     Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);   
  28.   
  29.     if (t != null) {   
  30.         throwable(request, response, t);   
  31.     } else {   
  32.         status(request, response);   
  33.     }   
  34.   
  35.     // 恢复ClassLoader   
  36.     Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());   
  37.   
  38. }  

不出意外的,请求下边就到了org.apache.catalina.core.StandardContextValve,源代码如下:

Java代码 Tomcat请求处理(五) -- 请求在容器间的流动 - guoyang1982 - 游龙

  1. public final void invoke(Request request, Response response) throws IOException,   
  2.         ServletException {   
  3.   
  4.     // 不允许请求访问META-INF和WEB-INF文件夹下的内容。   
  5.     MessageBytes requestPathMB = request.getRequestPathMB();   
  6.     if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))   
  7.             || (requestPathMB.equalsIgnoreCase("/META-INF"))   
  8.             || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))   
  9.             || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {   
  10.         notFound(response);   
  11.         return;   
  12.     }   
  13.   
  14.     // 如果系统正在重新载入中,那么暂停请求。   
  15.     boolean reloaded = false;   
  16.     while (context.getPaused()) {   
  17.         reloaded = true;   
  18.         try {   
  19.             Thread.sleep(1000);   
  20.         } catch (InterruptedException e) {   
  21.             ;   
  22.         }   
  23.     }   
  24.   
  25.     // 如果正在重载,停止老的WebappClassLoader并创建一个新的   
  26.     if (reloaded && context.getLoader() != null && context.getLoader().getClassLoader() != null) {   
  27.         Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());   
  28.     }   
  29.   
  30.     // 获得Wrapper对象   
  31.     Wrapper wrapper = request.getWrapper();   
  32.     if (wrapper == null) {   
  33.         notFound(response);   
  34.         return;   
  35.     } else if (wrapper.isUnavailable()) {   
  36.         wrapper = (Wrapper) container.findChild(wrapper.getName());   
  37.         if (wrapper == null) {   
  38.             notFound(response);   
  39.             return;   
  40.         }   
  41.     }   
  42.   
  43.     // 获得Listener列表   
  44.     Object instances[] = context.getApplicationEventListeners();   
  45.   
  46.     ServletRequestEvent event = null;   
  47.   
  48.     if ((instances != null) && (instances.length > 0)) {   
  49.         event = new ServletRequestEvent(((StandardContext) container).getServletContext(),   
  50.                 request.getRequest());   
  51.   
  52.         for (int i = 0; i < instances.length; i++) {   
  53.             if (instances[i] == null)   
  54.                 continue;   
  55.             if (!(instances[i] instanceof ServletRequestListener))   
  56.                 continue;   
  57.             ServletRequestListener listener = (ServletRequestListener) instances[i];   
  58.             try {   
  59.                 // 调用请求初始化事件   
  60.                 listener.requestInitialized(event);   
  61.             } catch (Throwable t) {   
  62.                 container.getLogger().error(   
  63.                         sm.getString("standardContext.requestListener.requestInit",   
  64.                                 instances[i].getClass().getName()), t);   
  65.                 ServletRequest sreq = request.getRequest();   
  66.                 sreq.setAttribute(Globals.EXCEPTION_ATTR, t);   
  67.                 return;   
  68.             }   
  69.         }   
  70.     }   
  71.   
  72.     // 调用Wrapper的Valve   
  73.     wrapper.getPipeline().getFirst().invoke(request, response);   
  74.   
  75.     if ((instances != null) && (instances.length > 0)) {   
  76.         for (int i = 0; i < instances.length; i++) {   
  77.             if (instances[i] == null)   
  78.                 continue;   
  79.             if (!(instances[i] instanceof ServletRequestListener))   
  80.                 continue;   
  81.             ServletRequestListener listener = (ServletRequestListener) instances[i];   
  82.             try {   
  83.                 // 调用请求结束事件   
  84.                 listener.requestDestroyed(event);   
  85.             } catch (Throwable t) {   
  86.                 container.getLogger().error(   
  87.                         sm.getString("standardContext.requestListener.requestDestroy",   
  88.                                 instances[i].getClass().getName()), t);   
  89.                 ServletRequest sreq = request.getRequest();   
  90.                 sreq.setAttribute(Globals.EXCEPTION_ATTR, t);   
  91.             }   
  92.         }   
  93.     }   
  94.   
  95. }  

这个Valve重要的是包括了对Listener的调用,最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。

Java代码 Tomcat请求处理(五) -- 请求在容器间的流动 - guoyang1982 - 游龙

  1. public final void invoke(Request request, Response response) throws IOException,   
  2.             ServletException {   
  3.   
  4.         boolean unavailable = false;   
  5.         Throwable throwable = null;   
  6.   
  7.         long t1 = System.currentTimeMillis();   
  8.         requestCount++;   
  9.         // 获得Wrapper所关联的对象   
  10.         StandardWrapper wrapper = (StandardWrapper) getContainer();   
  11.         // Servlet对象   
  12.         Servlet servlet = null;   
  13.         // 获得Context对象   
  14.         Context context = (Context) wrapper.getParent();   
  15.   
  16.         if (!context.getAvailable()) {   
  17.             response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm   
  18.                     .getString("standardContext.isUnavailable"));   
  19.             unavailable = true;   
  20.         }   
  21.   
  22.         if (!unavailable && wrapper.isUnavailable()) {   
  23.             container.getLogger().info(   
  24.                     sm.getString("standardWrapper.isUnavailable", wrapper.getName()));   
  25.             long available = wrapper.getAvailable();   
  26.             if ((available > 0L) && (available < Long.MAX_VALUE)) {   
  27.                 response.setDateHeader("Retry-After", available);   
  28.                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(   
  29.                         "standardWrapper.isUnavailable", wrapper.getName()));   
  30.             } else if (available == Long.MAX_VALUE) {   
  31.                 response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(   
  32.                         "standardWrapper.notFound", wrapper.getName()));   
  33.             }   
  34.             unavailable = true;   
  35.         }   
  36.   
  37.         try {   
  38.             if (!unavailable) {   
  39.                 // 分配一个Servelt实例   
  40.                 servlet = wrapper.allocate();   
  41.             }   
  42.         } catch (UnavailableException e) {   
  43.             container.getLogger().error(   
  44.                     sm.getString("standardWrapper.allocateException", wrapper.getName()), e);   
  45.             long available = wrapper.getAvailable();   
  46.             if ((available > 0L) && (available < Long.MAX_VALUE)) {   
  47.                 response.setDateHeader("Retry-After", available);   
  48.                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(   
  49.                         "standardWrapper.isUnavailable", wrapper.getName()));   
  50.             } else if (available == Long.MAX_VALUE) {   
  51.                 response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(   
  52.                         "standardWrapper.notFound", wrapper.getName()));   
  53.             }   
  54.         } catch (ServletException e) {   
  55.             container.getLogger().error(   
  56.                     sm.getString("standardWrapper.allocateException", wrapper.getName()),   
  57.                     StandardWrapper.getRootCause(e));   
  58.             throwable = e;   
  59.             exception(request, response, e);   
  60.             servlet = null;   
  61.         } catch (Throwable e) {   
  62.             container.getLogger().error(   
  63.                     sm.getString("standardWrapper.allocateException", wrapper.getName()), e);   
  64.             throwable = e;   
  65.             exception(request, response, e);   
  66.             servlet = null;   
  67.         }   
  68.   
  69.         boolean comet = false;   
  70.         if (servlet instanceof CometProcessor   
  71.                 && request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE) {   
  72.             comet = true;   
  73.             request.setComet(true);   
  74.         }   
  75.   
  76.         // 告知Request已经收到   
  77.         try {   
  78.             response.sendAcknowledgement();   
  79.         } catch (IOException e) {   
  80.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  81.             container.getLogger().warn(   
  82.                     sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e);   
  83.             throwable = e;   
  84.             exception(request, response, e);   
  85.         } catch (Throwable e) {   
  86.             container.getLogger().error(   
  87.                     sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e);   
  88.             throwable = e;   
  89.             exception(request, response, e);   
  90.             servlet = null;   
  91.         }   
  92.         MessageBytes requestPathMB = null;   
  93.         if (request != null) {   
  94.             requestPathMB = request.getRequestPathMB();   
  95.         }   
  96.            
  97.         request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,   
  98.                 ApplicationFilterFactory.REQUEST_INTEGER);   
  99.         request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);   
  100.         // 创建FilterChain   
  101.         ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();   
  102.         ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);   
  103.   
  104.         request.setComet(false);   
  105.   
  106.         try {   
  107.             // web.xml中的<jsp-file>标签   
  108.             String jspFile = wrapper.getJspFile();   
  109.             if (jspFile != null)   
  110.                 request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);   
  111.             else  
  112.                 request.removeAttribute(Globals.JSP_FILE_ATTR);   
  113.                
  114.             // 调用Filter   
  115.             if ((servlet != null) && (filterChain != null)) {   
  116.                 if (context.getSwallowOutput()) {   
  117.                     try {   
  118.                         SystemLogHandler.startCapture();   
  119.                         if (comet) {   
  120.                             filterChain.doFilterEvent(request.getEvent());   
  121.                             request.setComet(true);   
  122.                         } else {   
  123.                             filterChain.doFilter(request.getRequest(), response.getResponse());   
  124.                         }   
  125.                     } finally {   
  126.                         String log = SystemLogHandler.stopCapture();   
  127.                         if (log != null && log.length() > 0) {   
  128.                             context.getLogger().info(log);   
  129.                         }   
  130.                     }   
  131.                 } else {   
  132.                     if (comet) {   
  133.                         request.setComet(true);   
  134.                         filterChain.doFilterEvent(request.getEvent());   
  135.                     } else {   
  136.                         filterChain.doFilter(request.getRequest(), response.getResponse());   
  137.                     }   
  138.                 }   
  139.   
  140.             }   
  141.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  142.         } catch (ClientAbortException e) {   
  143.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  144.             throwable = e;   
  145.             exception(request, response, e);   
  146.         } catch (IOException e) {   
  147.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  148.             container.getLogger().error(   
  149.                     sm.getString("standardWrapper.serviceException", wrapper.getName()), e);   
  150.             throwable = e;   
  151.             exception(request, response, e);   
  152.         } catch (UnavailableException e) {   
  153.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  154.             container.getLogger().error(   
  155.                     sm.getString("standardWrapper.serviceException", wrapper.getName()), e);   
  156.   
  157.             wrapper.unavailable(e);   
  158.             long available = wrapper.getAvailable();   
  159.             if ((available > 0L) && (available < Long.MAX_VALUE)) {   
  160.                 response.setDateHeader("Retry-After", available);   
  161.                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(   
  162.                         "standardWrapper.isUnavailable", wrapper.getName()));   
  163.             } else if (available == Long.MAX_VALUE) {   
  164.                 response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(   
  165.                         "standardWrapper.notFound", wrapper.getName()));   
  166.             }   
  167.   
  168.         } catch (ServletException e) {   
  169.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  170.             Throwable rootCause = StandardWrapper.getRootCause(e);   
  171.             if (!(rootCause instanceof ClientAbortException)) {   
  172.                 container.getLogger().error(   
  173.                         sm.getString("standardWrapper.serviceException", wrapper.getName()),   
  174.                         rootCause);   
  175.             }   
  176.             throwable = e;   
  177.             exception(request, response, e);   
  178.         } catch (Throwable e) {   
  179.             request.removeAttribute(Globals.JSP_FILE_ATTR);   
  180.             container.getLogger().error(   
  181.                     sm.getString("standardWrapper.serviceException", wrapper.getName()), e);   
  182.             throwable = e;   
  183.             exception(request, response, e);   
  184.         }   
  185.   
  186.         if (filterChain != null) {   
  187.             if (request.isComet()) {   
  188.                 filterChain.reuse();   
  189.             } else {   
  190.                 filterChain.release();   
  191.             }   
  192.         }   
  193.   
  194.         // 释放Servlet对象   
  195.         try {   
  196.             if (servlet != null) {   
  197.                 wrapper.deallocate(servlet);   
  198.             }   
  199.         } catch (Throwable e) {   
  200.             container.getLogger().error(   
  201.                     sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);   
  202.             if (throwable == null) {   
  203.                 throwable = e;   
  204.                 exception(request, response, e);   
  205.             }   
  206.         }   
  207.   
  208.         try {   
  209.             if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {   
  210.                 wrapper.unload();   
  211.             }   
  212.         } catch (Throwable e) {   
  213.             container.getLogger().error(   
  214.                     sm.getString("standardWrapper.unloadException", wrapper.getName()), e);   
  215.             if (throwable == null) {   
  216.                 throwable = e;   
  217.                 exception(request, response, e);   
  218.             }   
  219.         }   
  220.         long t2 = System.currentTimeMillis();   
  221.   
  222.         long time = t2 - t1;   
  223.         processingTime += time;   
  224.         if (time > maxTime)   
  225.             maxTime = time;   
  226.         if (time < minTime)   
  227.             minTime = time;   
  228.   
  229.     }  

这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());),具体的还要进入方法内部去仔细看一下。comet方式以后再详细看.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值