SpringMVC之View

viewResolver组件会将viewName解析成view对象,view对象会调用render完成结果的处理。

View接口及实现类结构图:


不同的实现类有不同的视图效果:

1、VelocityView是用来和Velocity框架结合生成页面视图

2、FreeMarkerView是用来和FreeMarker框架结合生成页面视图

3、JstlView是用来生成jstl页面

4、RedirectView是生成页面跳转视图的。



View接口提供的接口方法还是比较简单的,这也是springMVC接口一贯的方式。

    public interface View {  
      
          
        String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";  
      
          
        String PATH_VARIABLES = View.class.getName() + ".pathVariables";  
      
          
        String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";  
      
          
        String getContentType();  
      
          
        void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;  
      
    }  

简单说一下render方法的最终实现机制

(1)model是一个Map结构,其实就是ModelAndView中map,存放了我们返回给请求的所有结果值

(2)request和response当然就是请求和返回了

render中做的操作就是将model中的值全部存放到request和response中,这样就完成了请求的处理操作,最终就是返回response请求。


DispatcherServlet中的处理流程操作:

    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()) {  
                //通过ViewResolver解析生成View对象  
                view = 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 '" + getServletName() + "'");  
                }  
            }  
            else {  
                //直接从ModelAndView中获取View对象  
                view = mv.getView();  
                if (view == null) {  
                    throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +  
                            "View object in servlet with name '" + getServletName() + "'");  
                }  
            }  
          
            try {  
                //调用View对象的render方法  
                view.render(mv.getModelInternal(), request, response);  
            }  
            catch (Exception ex) {  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +  
                            getServletName() + "'", ex);  
                }  
                throw ex;  
            }  
        }  

DispatcherServlet调用的是view的render方法


讲一下实现类做的操作

AbstractView实现了render方法,主要做的操作是将model中的参数和request中的参数全部都放到Request中,然后就转发Request就可以了。

    @Override  
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {  
        if (logger.isTraceEnabled()) {  
            logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +  
                " and static attributes " + this.staticAttributes);  
        }  
        //将model和request中的参数全部放到mergedModel中  
        Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);  
        //存放头部信息  
        prepareResponse(request, response);  
        //将mergedModel中的参数值放到request中  
        renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);  
    }  

createMergedOutputModel中的操作就是将所有的数据放到mergedModel中。

    protected Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request,  
                HttpServletResponse response) {  
      
            @SuppressWarnings("unchecked")  
            Map<String, Object> pathVars = (this.exposePathVariables ?  
                    (Map<String, Object>) request.getAttribute(View.PATH_VARIABLES) : null);  
      
            // Consolidate static and dynamic model attributes.  
            int size = this.staticAttributes.size();  
            size += (model != null ? model.size() : 0);  
            size += (pathVars != null ? pathVars.size() : 0);  
      
            Map<String, Object> mergedModel = new LinkedHashMap<String, Object>(size);  
            mergedModel.putAll(this.staticAttributes);  
            if (pathVars != null) {  
                mergedModel.putAll(pathVars);  
            }  
            if (model != null) {  
                mergedModel.putAll(model);  
            }  
      
            // Expose RequestContext?  
            if (this.requestContextAttribute != null) {  
                mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));  
            }  
      
            return mergedModel;  
        }  

prepareResponse中的操作就是在头部中添加信息。

    protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {  
            if (generatesDownloadContent()) {  
                response.setHeader("Pragma", "private");  
                response.setHeader("Cache-Control", "private, must-revalidate");  
            }  
        }  

renderMergedOutputModel是在子类中实现的,我们介绍一下我们经常使用的普通jsp源码使用的InternalResourceView

    @Override  
        protected void renderMergedOutputModel(  
                Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {  
      
            //把model中的所有数据放到request中  
            exposeModelAsRequestAttributes(model, request);  
      
            exposeHelpers(request);  
      
            //看看是否有跳转页面  
            String dispatcherPath = prepareForRendering(request, response);  
      
            // Obtain a RequestDispatcher for the target resource (typically a JSP).  
            RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);  
            if (rd == null) {  
                throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +  
                        "]: Check that the corresponding file exists within your web application archive!");  
            }  
      
            // If already included or response already committed, perform include, else forward.  
            if (useInclude(request, response)) {  
                response.setContentType(getContentType());  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");  
                }  
                //加载页面  
                rd.include(request, response);  
            }  
      
            else {  
                // Note: The forwarded resource is supposed to determine the content type itself.  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");  
                }  
                //转发操作  
                rd.forward(request, response);  
            }  
        }  
以上代码就完成了springMVC的所有处理操作,springMVC最终的操作就是调用request及response完成请求操作了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值