SpringMVC-请求处理的大致流程分析---doDispatch( )细节

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        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);//1.检查是否文件上传相关请求
                multipartRequestParsed = (processedRequest != request);
                  
                // Determine handler for the current request.2.根据当前请求,找到处理当前请求的处理器
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {  //3.没找到就抛异常或发送错误页面 404
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                //4.获取能执行这个类的所有方法的适配器(反射工具 AnnotationMethodHandlerAdapter)
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();//获取当前请求方式
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                //5.处理器的方法被调用了,适配器执行目标方法,返回一个 ModelAndView 对象 mv,返回页面自动装配在view属性里
              //目标方法执行完成后的返回值作为视图名,设置保存到 ModelAndView 中,无论目标方法怎么写,最终适配器执行完成以后都会将执行后的信息封装成ModelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            
                if (asyncManager.isConcurrentHandlingStarted()) {  //是否异步方法?
                    return;
                }

                applyDefaultViewName(processedRequest, mv);  //如果没有视图名,使用默认视图名
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            //6.转发到目标页面,根据方法最终执行完成后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

1) 所有请求过来,DispatcherServlet收到请求

2) 调用doDispatch( )方法进行处理

       (1).getHandler( ): 根据当前请求地址找到能处理这个请求的目标处理器;

       (2).getHandlerAdapter( ): 根据当前处理器类获取到能执行这个处理器方法的适配器;

       (3).使用刚才获取到的适配器(AnnotationMethodHandlerAdapter)执行目标方法;

       (4).目标方法执行后会返回一个ModelAndView对象;

       (5).根据ModelAndView的信息转发到具体的页面,并可以在请求域中取出ModelAndView中的模型数据。

posted @ 2021-03-09 16:43  CQ小强  阅读(78)  评论(0)    收藏  举报