SpringMVC页面访问流程(源码解析)

18 篇文章 0 订阅

SpringMVC有五大核心组件, DispatcherServlet, HandlerMapping, Controller, ModelAndView, ViewResolver; 其中以DispatcherServlet最为核心, 以下简称ds, 类似电脑cpu.
当容器接收到请求后, 会先到xml中找到对应servlet, 本质就是ds, 然后ds父类的service方法进行处理, 最后进入ds的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 err = null;
            Object dispatchException = null;

            try {
            	// 判断是否为文件上传
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                // 获取调用链路
                mappedHandler = this.getHandler(processedRequest);
                if(mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
				// 获取对应的handler适配器
                HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if(isGet || "HEAD".equals(method)) {
                    long lastModified = err1.getLastModified(request, mappedHandler.getHandler());
                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }

                    if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
				// 执行调用链中拦截器的pre方法
                if(!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
				// 利用反射技术调用Controller中的方法
                err = err1.handle(processedRequest, response, mappedHandler.getHandler());
                if(asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
				// 获取返回视图全路径
                this.applyDefaultViewName(processedRequest, err);
                // 执行调用链中拦截器的post方法
                mappedHandler.applyPostHandle(processedRequest, response, err);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
			// 视图解析
            this.processDispatchResult(processedRequest, response, mappedHandler, err, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
        }

    } finally {
        if(asyncManager.isConcurrentHandlingStarted()) {
            if(mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else if(multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }
    }
}
 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    Iterator var2 = this.handlerMappings.iterator();
	// 遍历所有的mapping
    HandlerExecutionChain handler;
    do {
        if(!var2.hasNext()) {
            return null;
        }

        HandlerMapping hm = (HandlerMapping)var2.next();
        if(this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
        }
		// 获取调用链,如果不为空, 直接返回
        handler = hm.getHandler(request);
    } while(handler == null);
    return handler;
}

// getHandler()方法调用了以下方法, 将拦截器添加到调用链中, 注意此时会添加SpringMVC内置的一个拦截器, 并且顺序为第一个
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, CorsConfiguration config) {
    if(CorsUtils.isPreFlightRequest(request)) {
        HandlerInterceptor[] interceptors = chain.getInterceptors();
        chain = new HandlerExecutionChain(new AbstractHandlerMapping.PreFlightHandler(config), interceptors);
    } else {
        chain.addInterceptor(new AbstractHandlerMapping.CorsInterceptor(config));
    }
    return chain;
}

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  HandlerInterceptor[] interceptors = this.getInterceptors();
    if(!ObjectUtils.isEmpty(interceptors)) {
    	// 注意此时是顺序调用拦截器的preHandle方法
        for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
            HandlerInterceptor interceptor = interceptors[i];
            if(!interceptor.preHandle(request, response, this.handler)) {
                this.triggerAfterCompletion(request, response, (Exception)null);
                return false;
            }
        }
    }
    return true;
}

handler方法经过一通调用最后调用以下方法
protected Object doInvoke(Object... args) throws Exception {
	...
    ReflectionUtils.makeAccessible(this.getBridgedMethod());
    return this.getBridgedMethod().invoke(this.getBean(), args);
	...
}

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
    HandlerInterceptor[] interceptors = this.getInterceptors();
    if(!ObjectUtils.isEmpty(interceptors)) {
    	// 注意此时是逆序调用拦截器的postHandle方法
        for(int i = interceptors.length - 1; i >= 0; --i) {
            HandlerInterceptor interceptor = interceptors[i];
            interceptor.postHandle(request, response, this.handler, mv);
        }
    }
}

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    booleanerrorView = false;
    if(exception != null) {
        if(exception instanceof ModelAndViewDefiningException) {
            this.logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException)exception).getModelAndView();
        } else {
            Object handler = mappedHandler != null?mappedHandler.getHandler():null;
            mv = this.processHandlerException(request, response, handler, exception);
            errorView = mv != null;
        }
    }

    if(mv != null && !mv.wasCleared()) {
    	// 解析视图
        this.render(mv, request, response);
        if(errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    } else if(this.logger.isDebugEnabled()) {
        this.logger.debug("Null ModelAndView returned to DispatcherServlet with name \'" + this.getServletName() + "\': assuming HandlerAdapter completed request handling");
    }

    if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        if(mappedHandler != null) {
        	// 逆序执行调用链中各拦截器的
            mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
        }
    }
}

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    Locale locale = this.localeResolver.resolveLocale(request);
    response.setLocale(locale);
    View view;
    // 判断本地是否已经加载过视图
    if(mv.isReference()) {
    	// 没有则创建视图解析器解析
        view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
        if(view == null) {
            throw new ServletException("Could not resolve view with name \'" + mv.getViewName() + "\' in servlet with name \'" + this.getServletName() + "\'");
        }
    } else {
    	// 如果有使用本地视图解析器
        view = mv.getView();
        if(view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name \'" + this.getServletName() + "\'");
        }
    }

    if(this.logger.isDebugEnabled()) {
        this.logger.debug("Rendering view [" + view + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
    }

    try {
        if(mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }

        view.render(mv.getModelInternal(), request, response);
    } catch (Exception var7) {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name \'" + this.getServletName() + "\'", var7);
        }

        throw var7;
    }
}

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
   Iterator var5 = this.viewResolvers.iterator();
    View view;
    do {
        if(!var5.hasNext()) {
            return null;
        }
// 获取视图解析器
        ViewResolver viewResolver = (ViewResolver)var5.next();
        // 解析视图
        view = viewResolver.resolveViewName(viewName, locale);
    } while(view == null);
    return view;
}

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
    HandlerInterceptor[] interceptors = this.getInterceptors();
    if(!ObjectUtils.isEmpty(interceptors)) {
    	// 注意此时是逆序调用拦截器的afterCompletion方法
        for(int i = this.interceptorIndex; i >= 0; --i) {
            HandlerInterceptor interceptor = interceptors[i];
            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            } catch (Throwable var8) {
                logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
            }
        }
    }
}

由于初次阅读SpringMVC源码, 可能会有很多不足, 如有问题, 欢迎评论指正, 感激不尽!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值