tomcat如何将请求分发到servlet

匿名 (未验证) 提交于 2019-12-03 00:19:01
Tomcat对一个请求进行解析时,首先会进行最首先的封装,将请求封装成Request对象。之后在一个类StandardWrapperValve中执行invoke方法。

 @Override     public final void invoke(Request request, Response response)         throws IOException, ServletException {          // Initialize local variables we may need         boolean unavailable = false;         Throwable throwable = null;         // This should be a Request attribute...         long t1=System.currentTimeMillis();         requestCount.incrementAndGet();         StandardWrapper wrapper = (StandardWrapper) getContainer();         Servlet servlet = null;         Context context = (Context) wrapper.getParent();          // Check for the application being marked unavailable         if (!context.getState().isAvailable()) {             response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,                            sm.getString("standardContext.isUnavailable"));             unavailable = true;         }          // Check for the servlet being marked unavailable         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;         }          // Allocate a servlet instance to process this request         try {             if (!unavailable) {                 servlet = wrapper.allocate(); //在可用情况下分配servlet,可用看看 unavailable变量的取值             }         } 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);         } catch (Throwable e) {             ExceptionUtils.handleThrowable(e);             container.getLogger().error(sm.getString("standardWrapper.allocateException",                              wrapper.getName()), e);             throwable = e;             exception(request, response, e);             servlet = null;         }          MessageBytes requestPathMB = request.getRequestPathMB();         DispatcherType dispatcherType = DispatcherType.REQUEST;         if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;         request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);         request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,                 requestPathMB);         // Create the filter chain for this request         ApplicationFilterChain filterChain =                 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); //重点,创建filterChain,根据代码实现的FilterswallowOutput 是Tomcat的Context的属性,用于设置System.out是否输出到日志,默认false  
//重点,servlet和filter生效的地方






继续跟进,看看
    @Override     public void doFilter(ServletRequest request, ServletResponse response)         throws IOException, ServletException {          if( Globals.IS_SECURITY_ENABLED ) {             final ServletRequest req = request;             final ServletResponse res = response;             try {                 java.security.AccessController.doPrivileged(                     new java.security.PrivilegedExceptionAction<Void>() {                         @Override                         public Void run()                             throws ServletException, IOException {                             internalDoFilter(req,res);//重点方法                             return null;                         }                     }                 );             } catch( PrivilegedActionException pe) {                 Exception e = pe.getException();                 if (e instanceof ServletException)                     throw (ServletException) e;                 else if (e instanceof IOException)                     throw (IOException) e;                 else if (e instanceof RuntimeException)                     throw (RuntimeException) e;                 else                     throw new ServletException(e.getMessage(), e);             }         } else {             internalDoFilter(request,response);//重点方法         }     }      private void internalDoFilter(ServletRequest request,                                   ServletResponse response)         throws IOException, ServletException {          // Call the next filter if there is one         if (pos < n) { //在 没有循环完filter时循环调用doFilter方法,一个责任链模式的经典实现  循环完跳出这个if方法块  
         ApplicationFilterConfig filterConfig = filters[pos++];// 获取filterList由
createFilterChain创建
   
if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); } else { filter.doFilter(request, response, this); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("filterChain.filter"), e); } return; } // We fell off the end of the chain -- call the servlet instance try { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(request); lastServicedResponse.set(response); } if (request.isAsyncSupported() && !servletSupportsAsync) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } // Use potentially wrapped request from this point if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); } else { servlet.service(request, response);//跳出循环后执行此方法,进入servlet的重点方法,对应到spring就是DispatcherServlet } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("filterChain.servlet"), e); } finally { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!