ModelAndView的生成与解析

在调用完我们的业务逻辑之后,springmvc会生成一个modelAndView对象,然后将他处理解析成view视图返回给前端。所以我们再来分析一下视图的生成以及解析规则。

接着我们上一节在handlerAdapter的初始化时说的调用handlerAdapter的handle方法,看看他到底是怎么生成view的

业务处理

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

视图生成

AbstractHandlerMethodAdapter  39  line

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return this.handleInternal(request, response, (HandlerMethod)handler);
    }

RequestMappinjgHandlerAdapter  464  line

protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		//检查请求是否合法   (请求方式以及session的检查)
        this.checkRequest(request);
        ModelAndView mav;
        //使用session加锁  这一块是false  所以看esle分支
        if (this.synchronizeOnSession) {
            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;
    }

业务逻辑的处理

RequestMappingHandlerAdapter   503  line

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		//包装一个ServletWebRequest
        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        ModelAndView var15;
        try {
        	一些准备工作  创建ModelFactory、ModelAndViewContainer、WebAsyncManager并设置一些属性值
            ......
            
			//执行业务
            invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
            if (asyncManager.isConcurrentHandlingStarted()) {
                result = null;
                return (ModelAndView)result;
            }
			
			//获取视图
            var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
        } finally {
            webRequest.requestCompleted();
        }

        return var15;
    }

执行业务

ServletInvocableHandlerMethod  50  line

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
		//解析请求的参数,并且执行我们的controller的方法,拿到返回值
        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);
                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 {
        	//处理请求结果  使用converter将结果写出去  outputstream流
            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;
        }
    }

处理请求结果 这一块会决定返回试图还是返回json数据

HandlerMethodReturnValueHandlerComposite  49 line

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
		//根据返回值与返回值类型去获取返回值处理的handler
        HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
        	//使用handler来处理返回结果
        	//如果是json数据,则使用RequestResponseBodyMethodProcessor
        	//如果是ModelAndView,则使用ModelAndViewMethodRetuenValueHandler来处理
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }

获取视图

RequestMappingHandlerAdapter  654  line

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
		//更新下默认的Model
        modelFactory.updateModel(webRequest, mavContainer);
        //如果需要返回视图,那么上面使用handler处理结果的时候会将这个置为false
        if (mavContainer.isRequestHandled()) {
            return null;
        } else {
            ModelMap model = mavContainer.getModel();
            ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
            if (!mavContainer.isViewReference()) {
            	//设置视图的名字
                mav.setView((View)mavContainer.getView());
            }

            if (model instanceof RedirectAttributes) {
                Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes();
                HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
                if (request != null) {
                    RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
                }
            }

            return mav;
        }
    }

设置视图的名字

DispatcherServlet  504  line

this.applyDefaultViewName(processedRequest, mv);

536  line

private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {
		//如果需要返回试图,并且视图名字为null,也就是我们没设置视图名字,那么使用默认的接口名作为视图名字
        if (mv != null && !mv.hasView()) {
            String defaultViewName = this.getDefaultViewName(request);
            if (defaultViewName != null) {
                mv.setViewName(defaultViewName);
            }
        }
    }

视图渲染

DispatcherServlet   546  line

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
        boolean errorView = false;
        异常处理
        ......

        if (mv != null && !mv.wasCleared()) {
        	//视图渲染  往下看
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } 
        ......
    }

DispatcherServlet   713  line

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
        response.setLocale(locale);
        String viewName = mv.getViewName();
        View view;
        if (viewName != null) {
        	//这一块使用我们配置的视图解析器去解析这个视图, 将视图名字拼上我们的请求转发的前后缀
            view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
        }
        try {
           	//视图渲染
            view.render(mv.getModelInternal(), request, response);
        } 
    }

AbstractView   141  line

public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        
        Map<String, Object> mergedModel = this.createMergedOutputModel(model, request, response);
        this.prepareResponse(request, response);
        //处理视图
        this.renderMergedOutputModel(mergedModel, this.getRequestToExpose(request), response);
    }

处理视图

InternalResourceView   46   line

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        this.exposeModelAsRequestAttributes(model, request);
        this.exposeHelpers(request);
        //获取页面跳转路径  视图解析其实就是获取页面跳转的地址,然后去进行页面跳转
        String dispatcherPath = this.prepareForRendering(request, response);
        RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
        if (rd == null) {
        } else {
            if (this.useInclude(request, response)) {
                response.setContentType(this.getContentType());
                rd.include(request, response);
            } else {
				//请求转发  这里也就是setvlet的forward方法
                rd.forward(request, response);
            }
        }
    }

这一块代码很繁杂,很乱,简单总结一下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值