SpringMVC工作流程(doDispatch源码级别)

如题,整理了一下SpringMVC的工作流程。

先看图:
在这里插入图片描述
再看文字:

  1. 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
  2. DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
  3. 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
  4. HandlerAdapter 会根据 Handler来调用真正的处理器来处理请求,并处理相应的业务逻辑。
  5. 处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
  6. ViewResolver 会根据逻辑 View 查找实际的 View。
  7. DispaterServlet 把返回的 Model 传给 View(视图渲染)。
  8. 把 View 返回给请求者(浏览器)

再看源码(主要看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 {
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                //1. 检查是否为文件上传请求
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                //2. 根据当前的请求地址找到哪个类能来处理
                //拿到方法的执行链(方法+拦截器=执行链),包含拦截器
                mappedHandler = this.getHandler(processedRequest);
                //3. 如果没有找到哪个处理器(控制器)能处理这个请求,就404或抛异常
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                //4. 根据当前处理器类拿到能执行这个类的所有方法的适配器(反射工具)
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (this.logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                    }

                    if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
	            //执行所有拦截器的preHandler,有一个拦截器返回false,目标方法就不执行,直接跳到afterCompletion
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                try {
                    //处理器Controller(控制器Handler)的方法被调用
                    //5. 适配器执行目标方法:将目标方法执行完成后的返回值作为视图名,保存到ModelAndView中。也就是说目标方法无论怎么写,适配器执行完成后都会将信息封装成ModelAndView。
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                } finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                }
                //若目标方法执行完没有返回视图名,设置一个默认的视图名
                this.applyDefaultViewName(request, mv);
                //目标方法只要正常,postHandler就会执行,有异常,都会来到afterCompletion
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var28) {
                dispatchException = var28;
            }
            //转发到目标页面
            //6. 根据方法最终完成后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取。
            //如果页面渲染有异常,会来到afterCompletion
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        } catch (Exception var29) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
        } catch (Error var30) {
            this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            return;
        } else {
            if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }
}

两个细节:
① getHandler()是怎么根据当前请求找到能处理它的类的?
getHandler()会返回目标处理器类的执行链,HandlerMapping保存了每一个处理器能处理哪些方法的映射信息,在HandlerMapping中找到这个请求的映射信息,获取到目标处理器类。
② getHandlerAdapter()是怎么找到能执行这个类的所有方法的适配器的?
AnnotationMethodHandlerAdapter能解析注解方法的适配器,根据当前处理器类,找到当前类的HandlerAdapter(适配器)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值