Tomcat源码解析七(Http请求过程解析(基于NIO)_容器解析过程)

在连接器对请求信息进行解析, 封装为Request和Response, 然后通过适配器CoyoteAdapter的service()方法调用引擎中管道pipeline的第一个Valve, 开始对请求进行处理;

CoyoteAdapter#service实现:

@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
    ...
    try {
        // Parse and set Catalina and configuration specific
        // request parameters
        postParseSuccess = postParseRequest(req, request, res, response);
        if (postParseSuccess) {
            //check valves if we support async
            request.setAsyncSupported(
                    connector.getService().getContainer().getPipeline().isAsyncSupported());
            /**
             * 调用StandardHost的pipeline对Request,Response进行处理
             * StandardHostValve保存在pipeline的first属性中
             * {@link org.apache.catalina.core.StandardEngineValve#invoke(Request, Response)}
             */
            connector.getService().getContainer().getPipeline().getFirst().invoke(
                    request, response);
        }
       ...
    } 
   ...
}

分析:

connector.getService()  ==> StandardService实例

connector.getService().getContainer()  ==>  StandardEngine实例

connector.getService().getContainer().getPipeline()  ==> StandardEngine.StandardPipeline实例

connector.getService().getContainer().getPipeline().getFirst()  ==> StandardEngineValve实例

connector.getService().getContainer().getPipeline().getFirst().invoke( request, response)实现:

@Override
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;
    }
    if (request.isAsyncSupported()) {
        request.setAsyncSupported(host.getPipeline().isAsyncSupported());
    }
    /**
     * 要求Host处理此请求
     * {@link AbstractAccessLogValve#invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response)}
     */
    host.getPipeline().getFirst().invoke(request, response);
}

分析:

  1. 获取请求的主机实例
  2. 获取Host的管道信息, 对请求进行处理

AbstractAccessLogValve#invoke实现:

@Override
public void invoke(Request request, Response response) throws IOException,
        ServletException {
    if (tlsAttributeRequired) {
        request.getAttribute(Globals.CERTIFICATES_ATTR);
    }
    /**
     * 执行下一个Valve
     * {@link ErrorReportValve#invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response)}
     */
    getNext().invoke(request, response);
}

分析:

  1. 权限日志信息配置
  2. 执行下一个Valve

ErrorReportValve#invoke实现:

@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
    /**
     * 执行下一个Valve
     * {@link org.apache.catalina.core.StandardHostValve#invoke(Request, Response)}
     */
    getNext().invoke(request, response);
    if (response.isCommitted()) {
        if (response.setErrorReported()) {
            try {
                response.flushBuffer();
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
            }
            response.getCoyoteResponse().action(ActionCode.CLOSE_NOW,
                    request.getAttribute(RequestDispatcher.ERROR_EXCEPTION));
        }
        return;
    }
    Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
    if (request.isAsync() && !request.isAsyncCompleting()) {
        return;
    }
    if (throwable != null && !response.isError()) {
        response.reset();
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    response.setSuspended(false);
    try {
        report(request, response, throwable);
    } catch (Throwable tt) {
        ExceptionUtils.handleThrowable(tt);
    }
}

分析:

  1. 执行下一个Valve
  2. 错误信息输出设置

StandardHostValve#invoke实现:

@Override
public final void invoke(Request request, Response response)throws IOException, ServletException {
    Context context = request.getContext();
    if (context == null) {
        return;
    }
    if (request.isAsyncSupported()) {
        request.setAsyncSupported(context.getPipeline().isAsyncSupported());
    }
    boolean asyncAtStart = request.isAsync();
    try {
        context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
        if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) {
            return;
        }
        try {
            if (!response.isErrorReportRequired()) {
                /**
                 * 调用StandardContext的pipeline对Request,Response进行处理
                 * StandardContextValve保存在pipeline的first属性中
                 * {@link StandardContextValve#invoke(Request, Response)}
                 */
                context.getPipeline().getFirst().invoke(request, response);
            }
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
            if (!response.isErrorReportRequired()) {
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
                throwable(request, response, t);
            }
        }
        response.setSuspended(false);
        Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        if (!context.getState().isAvailable()) {
            return;
        }
        if (response.isErrorReportRequired()) {
            AtomicBoolean result = new AtomicBoolean(false);
            response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
            if (result.get()) {
                if (t != null) {
                    throwable(request, response, t);
                } else {
                    status(request, response);
                }
            }
        }
        if (!request.isAsync() && !asyncAtStart) {
            context.fireRequestDestroyEvent(request.getRequest());
        }
    } finally {
        if (ACCESS_SESSION) {
            request.getSession(false);
        }
        context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
    }
}

分析: 

  1. 获取Context实例, 以及相关配置信息设置
  2. 获取Context的管道信息,对请求进行处理

StandardContextValve#invoke实现:

@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
    // 禁止直接访问WEB-INF或META-INF下的资源
    MessageBytes requestPathMB = request.getRequestPathMB();
    if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
            || (requestPathMB.equalsIgnoreCase("/META-INF"))
            || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
            || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // 选择用于此请求的包装器
    Wrapper wrapper = request.getWrapper();
    if (wrapper == null || wrapper.isUnavailable()) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // 确认请求
    try {
        response.sendAcknowledgement();
    } catch (IOException ioe) {
        container.getLogger().error(sm.getString(
                "standardContextValve.acknowledgeException"), ioe);
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    if (request.isAsyncSupported()) {
        request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
    }
    /**
     * 调用StandardWrapper的pipeline对Request,Response进行处理
     * StandardWrapperValve保存在pipeline的first属性中
     * {@link StandardWrapperValve#invoke(Request, Response)}
     */
    wrapper.getPipeline().getFirst().invoke(request, response);
}

分析:

  1. 禁止直接访问WEB-INF或META-INF下的资源
  2. 选择用于此请求的包装器Wrapper
  3. 确认请求
  4. 获取wrapper的管道信息, 对请求进行处理

StandardWrapperValve#invoke实现:

@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
   ...
    /**
     * 1.分配一个servlet实例以处理此请求
     */
    try {
        if (!unavailable) {
            /**
             * 获取一个Servlet实例
             */
            servlet = wrapper.allocate();
        }
    } catch (UnavailableException e) {
       ...
    }
    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);
    /**
     * 2.给当前请求创建一个Filter链
     */
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

    /**
     * 3.调用过滤器链, 在过滤器链的最后会调用servlet的service()方法
     */
    try {
        if ((servlet != null) && (filterChain != null)) {
            // Swallow output if needed
            if (context.getSwallowOutput()) {
                try {
                    SystemLogHandler.startCapture();
                    if (request.isAsyncDispatching()) {  //如果是异步请求
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else {
                        filterChain.doFilter(request.getRequest(),response.getResponse());
                    }
                } finally {
                    String log = SystemLogHandler.stopCapture();
                    if (log != null && log.length() > 0) {
                        context.getLogger().info(log);
                    }
                }
            } else {
                if (request.isAsyncDispatching()) {
                    request.getAsyncContextInternal().doInternalDispatch();
                } else {
                    /**
                     * 3.1 调用这个Filter链,Filter链中的最后一个Filter会调用Servlet
                     */
                    filterChain.doFilter(request.getRequest(), response.getResponse());
                }
            }
        }
     }
     ...
    } 
   
    // 如果存在过滤器链,则释放此请求的过滤器链
    if (filterChain != null) {
        filterChain.release();
    }
    // 取消分配已分配的servlet实例
    try {
        if (servlet != null) {
            wrapper.deallocate(servlet);
        }
    } catch (Throwable e) {
        ExceptionUtils.handleThrowable(e);
        container.getLogger().error(sm.getString("standardWrapper.deallocateException",
                         wrapper.getName()), e);
        if (throwable == null) {
            throwable = e;
            exception(request, response, e);
        }
    }
    ...
}

分析:

  1. 分配一个servlet实例以处理此请求
  2. 给当前请求创建一个Filter链
  3. 调用过滤器链, 在过滤器链的最后会调用servlet的service()方法

_1.StandardWrapper#allocate实现

@Override
public Servlet allocate() throws ServletException {

    //如果此时正在卸载servlet,则抛出异常
    if (unloading) {
        throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
    }

    boolean newInstance = false;

    // If not SingleThreadedModel, return the same instance every time
    if (!singleThreadModel) {
        /**
         * 如果实例未null或者还没有初始化完成, 则创建,以及初始化
         */
        if (instance == null || !instanceInitialized) {
            synchronized (this) {
                if (instance == null) {
                    try {
                        if (log.isDebugEnabled()) {
                            log.debug("Allocating non-STM instance");
                        }

                        /**
                         * 加载Servlet
                         * 注意:(1)我们不知道Servlet是否实现SingleThreadModel,直到我们加载它。
                         *       (2)此处调用loadServlet()方法加载Servlet是在接受到请求后,分配servlet处理请求时没有从缓存中获取到, 创建新的servlet实例后调用的
                         *       此处要与StandardContext中监听事件中的调用的loadServlet()方法区分
                         */
                        instance = loadServlet();
                        newInstance = true;
                        if (!singleThreadModel) {
                            // For non-STM, increment here to prevent a race
                            // condition with unload. Bug 43683, test case
                            // #3
                            countAllocated.incrementAndGet();
                        }
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        ExceptionUtils.handleThrowable(e);
                        throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                    }
                }
                if (!instanceInitialized) {
                    initServlet(instance);
                }
            }
        }
        /**
         * 将新创建的servlet实例放入实例池中
         */
        if (singleThreadModel) {
            if (newInstance) {
                // Have to do this outside of the sync above to prevent a
                // possible deadlock
                synchronized (instancePool) {
                    instancePool.push(instance);
                    nInstances++;
                }
            }
        } else {
            /**
             * 如果没有创建新servlet实例, 则直接返回获取到的实例
             */
            if (log.isTraceEnabled()) {
                log.trace("  Returning non-STM instance");
            }
            // For new instances, count will have been incremented at the
            // time of creation
            if (!newInstance) {
                countAllocated.incrementAndGet();
            }
            return instance;
        }
    }

    synchronized (instancePool) {
        while (countAllocated.get() >= nInstances) {
            // Allocate a new instance if possible, or else wait
            if (nInstances < maxInstances) {
                try {
                    instancePool.push(loadServlet());
                    nInstances++;
                } catch (ServletException e) {
                    throw e;
                } catch (Throwable e) {
                    ExceptionUtils.handleThrowable(e);
                    throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                }
            } else {
                try {
                    instancePool.wait();
                } catch (InterruptedException e) {
                    // Ignore
                }
            }
        }
        if (log.isTraceEnabled()) {
            log.trace("  Returning allocated STM instance");
        }
        countAllocated.incrementAndGet();
        /**
         * 从实例池中返回一个servlet实例
         */
        return instancePool.pop();
    }
}

_3. ApplicationFilterChain#doFilter实现:

@Override
public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {
    if( Globals.IS_SECURITY_ENABLED ) {
      ...
    } else {
        /**
         * 执行过滤器链
         */
        internalDoFilter(request,response);
    }
}

private void internalDoFilter(ServletRequest request,.ServletResponse response)throws IOException, ServletException {
    /**
     * 1. 如果存在过滤器, 则执行该过滤器
     */
    if (pos < n) {
        ApplicationFilterConfig filterConfig = filters[pos++];
        try {
            Filter filter = filterConfig.getFilter();
            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);
            }
        } 
        ...
        return;
    }
    /**
     * 2. 调用链执行完成之后, 调用servlet的service()方法
     */
    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方法;
             */
            servlet.service(request, response);
        }
    }
​​​​​​​    ...
}

分析:

  1. 如果存在过滤器, 则执行该过滤器
  2. 调用链执行完成之后, 调用servlet的service()方法

HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)实现:

 @Override
 public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {
     HttpServletRequest  request;
      HttpServletResponse response;
      try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
       } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
       }
       service(request, response);
    }
}

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    if (method.equals(METHOD_GET)) {
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            doGet(req, resp);
        } else {
            long ifModifiedSince;
            try {
                ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
            } catch (IllegalArgumentException iae) {
                ifModifiedSince = -1;
            }
            if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                maybeSetLastModified(resp, lastModified);
                doGet(req, resp);
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
        }
    } else if (method.equals(METHOD_HEAD)) {
        long lastModified = getLastModified(req);
        maybeSetLastModified(resp, lastModified);
        doHead(req, resp);
    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);
    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);
    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);
    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);
    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
}

至此, Http请求过程解析中容器的解析过程分析完成;

​​​​​​​

NIO模型下Tomcat中Http请求解析流程图:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值