java web 执行流程

组件说明

  1. Filter 主要用于对请求进行拦截和处理,可以用于对所有请求进行统一的预处理、过滤和修改操作。
  2. Interceptor 主要用于对 Controller 执行前、执行后以及渲染前的拦截和处理操作,在 Controller 与视图之间添加拦截器链,可以灵活地增加或删除拦截器。
  3. @ControllerAdvice 主要用于定义全局异常处理器和全局数据绑定器,它只能捕捉到 Controller 层抛出的异常,无法捕捉到更底层的异常。
  4. AOP 主要用于在运行时动态地将代码片段插入到现有代码的特定位置,并根据切面定义的规则来执行相应的行为,可用于处理各种通用问题,例如日志记录、事务控制、权限验证等。
  5. Controller 是处理 HTTP 请求并返回响应结果的核心组件之一,它通过注解的方式来标识控制器组件。在实际开发中,控制器逻辑通常会比较复杂,需要对请求参数进行校验、调用 Service 层进行逻辑处理、将结果封装成视图并返回给客户端等多个步骤。

执行顺序 Filter -> Interceptor -> @ControllerAdvice -> AOP -> Controller

  1. Filter:HTTP 请求进入 Servlet Container 后,首先由 Filter 进行拦截和处理。因此,Filter 的执行顺序最高。
  2. Interceptor:在经过 Filter 的处理后,请求会交给 DispatcherServlet 进行处理。DispatcherServlet 会根据请求路径映射到对应的 Controller 中去。在 Controller 执行前、执行后以及渲染前,可能会有多个 Interceptor 对其进行拦截和处理。Interceptor 是链式调用的,而且可以配置多个拦截器,因此,Interceptor 的执行顺序由配置的顺序决定。
  3. @ControllerAdvice:在 Controller 执行过程中,如果抛出了异常,会被捕获并由全局异常处理器进行处理。除此之外,全局数据绑定器和全局数据预处理器也会在执行过程中被调用。
  4. AOP:在 Controller 执行过程中,可能会使用 AOP 对其进行增强,例如添加事务控制、日志记录等功能。AOP 可以在请求执行前、执行后以及出现异常时进行拦截和处理。
  5. Controller:Controller 是最后一个处理请求的组件。在执行过程中,会根据请求参数、请求头、路径变量等信息来获取请求资源,并将处理结果封装成视图返回给客户端。

以上其实有一点不对的就是AOP 我们根据源码 检验一下

请求通过 tomcat filter 将请去转发到springmvc
  • /org/apache/catalina/core/ApplicationFilterChain.java:189
    • filter.doFilter(request, response, this);
  • /org/springframework/web/filter/OncePerRequestFilter.java:117
  • doFilterInternal(httpRequest, httpResponse, filterChain);

省略无关代码直接到 springmvc 核心代码 dispatcherServlet

  • DispatcherServlet 的核心方法,负责协调整个请求处理过程
  • DispatcherServlet 是一个 Servlet
  • /org/springframework/web/servlet/DispatcherServlet.java:963
  • doDispatch(request, response);

核心的方法解析

  1. DispatcherServlet:
  • 核心组件之一,所有的请求都会经过它进行处理。DispatcherServlet 负责接收 HTTP 请求、调用相应的控制器进行处理,并将处理结果返回给客户端。
  • doDispatch() 方法首先会通过 HandlerMapping 获取当前请求对应的 HandlerExecutionChain 对象,该对象包含了请求路径所对应的处理器及其拦截器。
    * 如果未找到匹配的处理器,doDispatch() 方法会调用 noHandlerFound() 方法,返回 404 状态码。
  1. HandlerMapping:
  • 是将请求路径映射到相应的处理器(Controller)的组件。在执行 DispatcherServlet 之前,会先执行 HandlerMapping 中的 lookupHandler() 方法,根据请求路径找到对应的处理器。
  • DispatcherServlet将要调用的方法及其参数等相关信息封装成一个HandlerExecutionChain对象并封装到ModelAndView对象中返回给DispatcherServlet。
  1. HandlerAdapter:
  • 是调用处理器(Controller)的组件。在找到处理器之后,会使用 HandlerAdapter 将处理器包装成可调用的形式,然后调用其 handle() 方法进行处理。
  • HandlerAdapter将处理器对象适配成能够处理请求的处理器执行链(HandlerExecutionChain)。因为不同类型的处理器对象需要使用不同的HandlerAdpater进行适配。
  • handle 方法会使用 HandlerAdapter 执行处理器的业务逻辑,并将处理结果封装成 ModelAndView 对象返回。
  1. HandlerInterceptor:
  • 是拦截请求和处理器调用之间的组件。HandlerInterceptor 中定义了多个拦截器方法,可以用于在处理器执行前、执行后以及渲染前进行相关处理。
  • 如果找到了匹配的处理器,doDispatch() 方法会执行与处理器相关联的拦截器,在 HandlerInterceptor.preHandle()、postHandle() 方法中可以进行权限验证等操作。
    • 如果所有拦截器的 preHandle()、postHandle() 方法均返回 true,则说明请求可以继续处理。
  1. HandlerExceptionResolver:
  • 是中用于处理异常的组件。当出现异常时,会通过 ExceptionResolver 将异常转化为 ModelAndView 对象,并将其交给 DispatcherServlet 进行处理。
  • 最后则会调用 processDispatchResult() 方法进行异常处理。
源码
// DispatcherServlet 的 service 方法
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 1. 查找 HandlerMapping,获取 HandlerExecutionChain
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }
            // 2. 使用 HandlerAdapter 将处理器包装成可调用的形式
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // 3. 调用拦截器的预处理方法
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // 4. 执行Handler调用
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            // 5. 调用拦截器的后处理方法
            mappedHandler.applyPostHandle(processedRequest, response, mv);

        } catch (Exception ex) {
            dispatchException = ex;
        } catch (Throwable err) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }

        // 6. 处理异常
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception e) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, e);
    }
    catch (Throwable err) {
        triggerAfterCompletion(processedRequest, response, mappedHandler,
            new NestedServletException("Handler processing failed", err));
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            // Instead of postHandle and afterCompletion
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            return;
        }
        if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
        }
    }
}

// 查找 HandlerMapping 的 getHandler 方法
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 获取所有的 HandlerMapping
    if (this.handlerMappings != null) {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                    "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            // 查找 HandlerExecutionChain
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

// 使用 HandlerAdapter 调用处理器的 handle 方法
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {

    // ...

    try {
        // 1. 对请求参数进行解析和验证
        mavContainer.setRequestHandled(false);
        // 2. 调用处理器的 handle 方法
        Object result = invokeHandlerMethod(request, response, handler);
        // 3. 处理处理器的返回值
        if (result instanceof ModelAndView) {
            mav = (ModelAndView) result;
        }
        else {
            mav = new ModelAndView(getViewName(request));
            mav.addObject(DEFAULT_MODEL_NAME, result);
        }
    } catch (Exception ex) {
        if (!mavContainer.isRequestHandled()) {
            mav = handleException(request, response, handler, ex);
            mavContainer.setRequestHandled(true);
        }
        else {
            logger.debug("Exception cleared after handling of request [" + request.getRequestURI() + "]", ex);
        }
    }

    // ...

    return mav;
}

posted @ 2023-04-13 15:52  vx_guanchaoguo0  阅读(176)  评论(0编辑  收藏  举报