一文带你了解SpringMVC源码

文章目录

  • 一、图解SpringMVC
    • 1.1 执行流程图
    • 1.2 UML序列图
  • 二、源码分析
    • 2.1 doService方法
    • 2.2 doDispatch方法(核心方法)
    • 2.3 获取执行链
      • 2.3.1 getHandler方法
      • 2.3.2 AbstractHandlerMapping#getHandlerInternal方法
      • 2.3.3 AbstractHandlerMapping#lookupHandlerMethod
      • 2.3.4 RequestMappingInfo#getMatchingCondition 方法
    • 2.4 获取处理器适配器
      • 2.4.1 getHandlerAdapter方法
    • 2.5 执行拦截器的前置方法
    • 2.6 执行处理器
      • 2.6.1 RequestMappingHandlerAdapter#handleInternal 方法
      • 2.6.2 invokeHandlerMethod
      • 2.6.3 getDataBinderFactory
      • 2.6.4 initModel
      • 2.6.5 invokeModelAttributeMethods
      • 2.6.6 ServletInvocableMethod#invokeAndHandle方法
      • 2.6.7 InvocableHandlerMethod#getMethodArgumentValues
    • 2.7 处理程序调用返回的结构
      • 2.7.1 processDispatchResult
  • 总结


一、图解SpringMVC

1.1 执行流程图

一文带你了解SpringMVC源码_第1张图片

  1. 客户端用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet根据请求去HandlerMapping获取处理器
  3. HandlerMapping返回执行链,执行链中包含处理器拦截器数组HandlerInterceptor[]、列表List和真正的处理器handler
  4. DispatcherServlet通过处理器适配器HandlerAdapter调用处理器Handler(也叫Controller)。
  5. 执行处理器Handler
  6. Handler返回ModelAndView给处理器适配器HandlerAdapter
  7. HandlerAdapterModelAndView返回给DispatcherServlet
  8. DispatcherServletModelAndView传给视图解析器ViewResolver
  9. 视图解析器ViewResolver解析后返回具体的视图View
  10. 渲染视图
  11. 响应用户

1.2 UML序列图

提示:自己看着代码画的,如果有错误欢迎大佬指正
一文带你了解SpringMVC源码_第2张图片

二、源码分析

​ 在用户发起请求后经过FrameworkServlet后会进入DispatcherServletdoService方法。

2.1 doService方法

  • doService方法。该方法主要是将一些参数设置到请求中让handler和view对象可用。然后请求核心方法doDispatch()

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        this.logRequest(request);
        Map<String, Object> attributesSnapshot = null;
        if (WebUtils.isIncludeRequest(request)) {
            attributesSnapshot = new HashMap();
            Enumeration attrNames = request.getAttributeNames();
    
            label95:
            while(true) {
                String attrName;
                do {
                    if (!attrNames.hasMoreElements()) {
                        break label95;
                    }
    
                    attrName = (String)attrNames.nextElement();
                } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
    
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    
        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
        if (this.flashMapManager != null) {
            FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
            if (inputFlashMap != null) {
                request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
            }
    
            request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
            request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
        }
    
        try {
            this.doDispatch(request, response);
        } finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot);
            }
    
        }
    
    }
    

2.2 doDispatch方法(核心方法)

  • 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;
                Object dispatchException = null;
    
                try {
                    // 判断这个请求是否是Multipart,比如文件上传就是Multipart请求。如果是Multipart请求就交给multipartResolver处理,如果不是Multipart返回当前的请求。
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    // 获取处理器
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
    				// 获取处理器适配器
                    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 ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
    				
                    // 执行拦截器中的前置方法,如果返回false就不再执行
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    				
                    // 执行真正的处理方法(Controller中的方法)
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    // 如果ModelAndView中没有视图引用,那么申请设置默认的视图名称
                    this.applyDefaultViewName(processedRequest, mv);
                    // 执行拦截器中的后置方法
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
    
                // 处理程序调用返回的结构进行处理 详情见2.7
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (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);
            }
    
        }
    }
    

2.3 获取执行链

2.3.1 getHandler方法

  • 在getHandler(processedRequest)里面通过遍历所有的handlerMapping,调用handlerMapping对象中的getHandler(request)方法获得HandlerExecutionChain对象。其中关键方法为 mapping.getHandler(request);下方详解

    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            Iterator var2 = this.handlerMappings.iterator();
    
            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
    
        return null;
    }
    

2.3.2 AbstractHandlerMapping#getHandlerInternal方法

  • 在进入AbstractHandlerMapping中的getHandler方法后主要方法就是getHandlerInternal,其他就是构造执行链,故直接看getHandlerInternal方法

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        // 从请求中获取lookupPath
        String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
        request.setAttribute(LOOKUP_PATH, lookupPath);
        // mappingRegistry是映射关系注册中心,其中维护mapping到处理程序handlerMethod的映射关系
    	// 取锁
        this.mappingRegistry.acquireReadLock();
    
        HandlerMethod var4;
        try {
            // 获取处理器,lookupHandlerMethod方法,见2.5
            HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);
            var4 = handlerMethod != null ? handlerMethod.createWithResolvedBean() : null;
        } finally {
            // 释放锁
            this.mappingRegistry.releaseReadLock();
        }
    
        return var4;
    }
    

2.3.3 AbstractHandlerMapping#lookupHandlerMethod

  • 该方法会通过lookupPath和request去匹配对应的处理器(controller里的方法)

    @Nullable
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
        // 根据路径获取路径匹配的所有规则。
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            // 将通过路径初次匹配的,去RequestMappingInfo中匹配,总共有七个规则匹配详情见下文#getMatchingCondition 方法
            this.addMatchingMappings(directPathMatches, matches, request);
        }
    
        if (matches.isEmpty()) {
            // 若上方没有找到匹配的,则将注册中心所有的映射拿去匹配
            this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
    
        if (!matches.isEmpty()) {
            AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
            if (matches.size() > 1) {
                Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
                matches.sort(comparator);
                bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace(matches.size() + " matching mappings: " + matches);
                }
    
                if (CorsUtils.isPreFlightRequest(request)) {
                    return PREFLIGHT_AMBIGUOUS_MATCH;
                }
    
                AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    // 找到了两个处理器,抛异常
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    String uri = request.getRequestURI();
                    throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
                }
            }
    
            request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
            this.handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        } else {
            return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
        }
    }
    

2.3.4 RequestMappingInfo#getMatchingCondition 方法

  • 该方法会将不匹配的信息过滤掉

    @Nullable
    public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
        // 请求方法过滤器
        RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
        if (methods == null) {
            return null;
        } else {
            // 请求参数过滤器
            ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
            if (params == null) {
                return null;
            } else {
                // 头字段过滤器
                HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
                if (headers == null) {
                    return null;
                } else {
                    // 请求媒体类型过滤器
                    ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
                    if (consumes == null) {
                        return null;
                    } else {
                        // 应答媒体类型过滤器
                        ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
                        if (produces == null) {
                            return null;
                        } else {
                            // 模式请求路径过滤器
                            PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
                            if (patterns == null) {
                                return null;
                            } else {
                                // 自定义请求过滤器
                                RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
                                return custom == null ? null : new RequestMappingInfo(this.name, patterns, methods, params, headers, consumes, produces, custom.getCondition());
                            }
                        }
                    }
                }
            }
        }
    }
    

2.4 获取处理器适配器

  • 在获取到处理器后,接着就是去获取处理器适配器

    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    

2.4.1 getHandlerAdapter方法

  • 点开代码看看,看看细节。主要是循环当前所有的handlerAdapters,通过supports()判断是否支持当前handlerMethod,这种循环比对思想在Spring MVC源码随处可见。

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();
    
            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }
    
        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }
    

2.5 执行拦截器的前置方法

  • 执行执行链中拦截器的前置方法

    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    	return;
    }
    
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            // 遍历拦截器
            for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                HandlerInterceptor interceptor = interceptors[i];
                // 若拦截器返回false则终止
                if (!interceptor.preHandle(request, response, this.handler)) {
                    // 释放资源
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false;
                }
            }
        }
    
        return true;
    }
    

2.6 执行处理器

  • 处理器适配器调用handle方法

    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    

2.6.1 RequestMappingHandlerAdapter#handleInternal 方法

  • 处理器调用handle方法后会进入AbstractHandlerMethodAdapter#handle 接着进入RequestMappingHandlerAdapter#handleInternal

    protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        // 检查请求
        this.checkRequest(request);
        ModelAndView mav;
        // 根据session来判断是否需要加锁调用
        if (this.synchronizeOnSession) {
            // 获取session
            HttpSession session = request.getSession(false);
            if (session != null) {
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized(mutex) {
                    // 执行处理器方法
                    mav = this.invokeHandlerMethod(request, response, handlerMethod);
                }
            } else {
                mav = this.invokeHandlerMethod(request, response, handlerMethod);
            }
        } else {
            mav = this.invokeHandlerMethod(request, response, handlerMethod);
        }
    
        if (!response.containsHeader("Cache-Control")) {
            if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
            } else {
                this.prepareResponse(response);
            }
        }
    
        return mav;
    }
    

2.6.2 invokeHandlerMethod

  • 调用处理器中的方法。需要构建参数,

    @Nullable
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
    
        ModelAndView var15;
        try {
            // 获取数据绑定工厂 详情见 2.6.3
            WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
            // 获取模型工厂 ModelFactory作用是在控制器方法调用前初始化Model模型,调用后对Model模型进行更新。 
            // 逻辑与获取数据绑定工厂差不多,先获取SessionAttributesHandler,再获取@ModelAttribute注解且没有被@RequestMapping注解的方法,最后构建出ModelFactory。
            ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
            // 根据handlerMethod创建ServletInvocableHandlerMethod,ServletInvocableHandlerMethod用于对处理程序的返回值进行处理和ResponseStatus处理。
            ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
            if (this.argumentResolvers != null) {
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            }
    
            if (this.returnValueHandlers != null) {
                invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            }
    
            invocableMethod.setDataBinderFactory(binderFactory);
            invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
            
            // 实例化ModelAndViewContainer容器,把request里面的属性名为"org.springframework.web.servlet.DispatcherServlet.INPUT_FLASH_MAP"的重定向参数注入到容器中的model模型中。FlashMap的作用是在redirect中传递参数。重定向是会生成新的request,那么传递参数就不能直接用request进行传递。
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
            // 初始化数据模型容器,详情见2.6.4
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);
            mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
            // 处理一些异步请求
            AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
            asyncWebRequest.setTimeout(this.asyncRequestTimeout);
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
            asyncManager.setTaskExecutor(this.taskExecutor);
            asyncManager.setAsyncWebRequest(asyncWebRequest);
            asyncManager.registerCallableInterceptors(this.callableInterceptors);
            asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
            Object result;
            if (asyncManager.hasConcurrentResult()) {
                result = asyncManager.getConcurrentResult();
                mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
                asyncManager.clearConcurrentResult();
                LogFormatUtils.traceDebug(this.logger, (traceOn) -> {
                    String formatted = LogFormatUtils.formatValue(result, !traceOn);
                    return "Resume with async result [" + formatted + "]";
                });
                invocableMethod = invocableMethod.wrapConcurrentResult(result);
            }
    
            // ServletInvocableMethod中的invokeAndHandle()其实是间接调用handlerMethod,然后处理handlerMethod的返回值。详情见2.6.6
            invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
            if (asyncManager.isConcurrentHandlingStarted()) {
                result = null;
                return (ModelAndView)result;
            }
    		
            // 获取ModelAndView对象
            var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
        } finally {
            webRequest.requestCompleted();
        }
    
        return var15;
    }
    

2.6.3 getDataBinderFactory

  • 该方法用于创建绑定工厂,先遍历全局的属性编辑器,被@ControllerAdvice里添加了@InitBinder注解的方法,再遍历controller类里添加了@InitBinder注解的方法,根据这些方法先生成InvocableHandlerMethod列表,再生成数据绑定工厂。

    private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
        Class<?> handlerType = handlerMethod.getBeanType();
        // 从initBinderCache缓存中获取该类的所有添加了 @InitBinder 注解的方法
        Set<Method> methods = (Set)this.initBinderCache.get(handlerType);
        if (methods == null) {
            // 查询该类所有添加了@InitBinder 注解的方法并加入缓存
            methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
            this.initBinderCache.put(handlerType, methods);
        }
    
        List<InvocableHandlerMethod> initBinderMethods = new ArrayList();
        
        // 遍历被@ControllerAdvice注解全局类,methodSet中存放该类中添加了@InitBinder注解的方法
        this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
            if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
                Object bean = controllerAdviceBean.resolveBean();
                Iterator var6 = methodSet.iterator();
    
                while(var6.hasNext()) {
                    Method method = (Method)var6.next();
                    // 通过createInitBinderMethod(bean, method)方法创建InvocableHandlerMethod对象(用于参数准备,准备当中会用到WebDataBinderFactory创建WebDataBinder实例进行参数转换解析绑定,方法调用),并且放入到initBinderMethods集合中。
                    initBinderMethods.add(this.createInitBinderMethod(bean, method));
                }
            }
    
        });
        Iterator var5 = methods.iterator();
    	
        while(var5.hasNext()) {
            Method method = (Method)var5.next();
            Object bean = handlerMethod.getBean();
            initBinderMethods.add(this.createInitBinderMethod(bean, method));
        }
    
        return this.createDataBinderFactory(initBinderMethods);
    }
    

2.6.4 initModel

  • 初始化模型,将添加了@ModelAttribute 的方法和参数添加了@ModelAttribute添加到模型中

    public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod)
    			throws Exception {
    
        // 首先从request中获取检索@SessionAttribute中名称的属性,以Map的结构存储起来,并且放入到ModelAndViewContainer容器的model中。
        Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
    	// 合并到数据模型容器中
        container.mergeAttributes(sessionAttributes);
        // 调用模型属性方法来填充模型。只有在模型中不存在的情况下才会添加属性。详情见2.6.5
        invokeModelAttributeMethods(request, container);
    
        // 遍历参数中被@ModelAttribute的参数
    	// 在@SessionAttributes中找到@ModelAttribute参数。
        for (String name : findSessionAttributeArguments(handlerMethod)) {
            if (!container.containsAttribute(name)) {
                // 从SessionAttributeStore中获取属性,不存在则返回空
                Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
                if (value == null) {
                    throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
                }
                container.addAttribute(name, value);
            }
        }
    }
    

2.6.5 invokeModelAttributeMethods

  • 将添加了@ModelAttribute注解的方法返回值,添加到模型中

    private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)
    			throws Exception {
    
        while (!this.modelMethods.isEmpty()) {
            InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
            ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
            Assert.state(ann != null, "No ModelAttribute annotation");
            // 模型中是否已经有了该属性,
            if (container.containsAttribute(ann.name())) {
                // 是否禁止绑定
                if (!ann.binding()) {
                    container.setBindingDisabled(ann.name());
                }
                continue;
            }
    		
            // 调用方法获取返回值
            Object returnValue = modelMethod.invokeForRequest(request, container);
            // 方法是否有返回值
            if (!modelMethod.isVoid()){
                // 获取返回值名称,其规则为:如果@ModelAttribute注解设置value和name属性了,优先选择value和name属性作为model中的key,如果没有设置value和name属性,选择被@ModelAttribute注解的handlerMethod的返回类型名称(首字母小写)作为model中的key。
                // 注:若返回类型为列表或数组则,名称为 返回类型+List 如stringList
                String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
                if (!ann.binding()) {
                    container.setBindingDisabled(returnValueName);
                }
                if (!container.containsAttribute(returnValueName)) {
                    container.addAttribute(returnValueName, returnValue);
                }
            }
        }
    }
    

2.6.6 ServletInvocableMethod#invokeAndHandle方法

  • 调用handlerMethod方法,并处理返回值

    public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 调用handlerMethod方法(controller里的方法),会先用InvocableHandlerMethod#getMethodArgumentValues()的方法获取所有参数数组,初始化参数。详情见2.6.7 。 参数解析完成后会通过反射调用方法
        Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
        // 设置响应状态
        this.setResponseStatus(webRequest);
        if (returnValue == null) {
            if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
                this.disableContentCachingIfNecessary(webRequest);
                // 设置不需要驶入解析,例如@ResponseBody方法,因此不需要视图解析。当控制器方法声明ServletResponse或OutputStream类型的参数时,也可以设置此标志。
                mavContainer.setRequestHandled(true);
                return;
            }
        } else if (StringUtils.hasText(this.getResponseStatusReason())) {
            mavContainer.setRequestHandled(true);
            return;
        }
    
        mavContainer.setRequestHandled(false);
        Assert.state(this.returnValueHandlers != null, "No return value handlers");
    
        try {
            // 返回值处理,与前面的逻辑差不多,都是遍历所有的返回值处理器,判断是否支持该返回值类型,支持则调用处理器处理
            this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
        } catch (Exception var6) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace(this.formatErrorForReturnValue(returnValue), var6);
            }
    
            throw var6;
        }
    }
    

2.6.7 InvocableHandlerMethod#getMethodArgumentValues

  • InvocableHandlerMethod中的getMethodArgumentValues()这个方法是获取handlerMethod的参数。首先获取handlerMethod中的所有参数数组,数组类型是MethodParameter。遍历参数数组,给每一个参数初始化parameterNameDisconverer(参数名称发现器)。

    protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
    			Object... providedArgs) throws Exception {
    
        // 获取方法参数数组
        MethodParameter[] parameters = getMethodParameters();
        if (ObjectUtils.isEmpty(parameters)) {
            return EMPTY_ARGS;
        }
    
        Object[] args = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            args[i] = findProvidedArgument(parameter, providedArgs);
            if (args[i] != null) {
                continue;
            }
            // 判断参数解析链是否支持parameter这种类型的参数解析。
            if (!this.resolvers.supportsParameter(parameter)) {
                throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
            }
            try {
                // 遍历已注册的参数解析器解析参数,若找不到合适的解析器则抛出IllegalArgumentException异常
                args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
            }
            catch (Exception ex) {
                // Leave stack trace for later, exception may actually be resolved and handled...
                if (logger.isDebugEnabled()) {
                    String exMsg = ex.getMessage();
                    if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
                        logger.debug(formatArgumentError(parameter, exMsg));
                    }
                }
                throw ex;
            }
        }
        return args;
    }
    

2.7 处理程序调用返回的结构

2.7.1 processDispatchResult

  • 要么是ModelAndView,要么解析成ModelAndView的异常。如果异常不为空且是ModelAndViewDefiningException类型的异常,那么把视图解析成ModelAndViewDefiningException特定的视图。如果异常不为空且不是ModelAndViewDefiningException类型的异常,那么调用 processHandlerException()让HandlerExceptionResovlers中的异常处理器来处理。

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
        boolean errorView = 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) {
                // 清理错误属性(status_code、exception_type、message、exception、request_uri、servlet_name)
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("No view rendering, null ModelAndView returned.");
        }
    
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }
    
        }
    }
    

总结

  • 第一次写框架源码分析,略为粗糙,并且其中有许多错误。望大佬不吝赐教。

你可能感兴趣的:(Java,springmvc,springmvc,java)