• View 渲染


    在Spring MVC 中,controllers不负责具体的页面渲染,仅仅是调用业务逻辑并返回model数据给view层,至于view层具体怎么展现,由专门的view层具体负责,这就是MVC模式,业务层与展示层是松耦合的。那么,Spring MVC是如何解耦合请求处理逻辑和页面渲染的呢?

    视图解析器

    请求进入DispathServlet后,通过HandlerMapping找到对应的HandlerExecutionChain,
    最后交由HandlerAdapter来执行最终Handler【也就是Controller中的Action】,最终得到ModelAndView,然后再次交给DispatchServlet来处理,并执行render方法处理渲染逻辑,如下:

     1protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    2        Locale locale =
    3                (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
    4        response.setLocale(locale);
    5
    6        View view;
    7        String viewName = mv.getViewName();
    8        if (viewName != null) {
    9            // 通过ViewResolver 来获取真正的View对象
    10            view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
    11
    12            }
    13        }
    14        else {
    15            view = mv.getView();
    16            }
    17        }
    18        try {
    19            if (mv.getStatus() != null) {
    20                response.setStatus(mv.getStatus().value());
    21            }
    22           //通过执行View对象的render方法来真正执行视图渲染的逻辑
    23            view.render(mv.getModelInternal(), request, response);
    24        }
    25        catch (Exception ex) {
    26            throw ex;
    27        }
    28    }

     1    protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
    2            Locale locale, HttpServletRequest request) throws Exception {
    3
    4        if (this.viewResolvers != null) {
    5            for (ViewResolver viewResolver : this.viewResolvers) {
    6//遍历ViewResolver集合 来获取合适的ViewResolver 对象
    7                View view = viewResolver.resolveViewName(viewName, locale);
    8                if (view != null) {
    9                    return view;
    10                }
    11            }
    12        }
    13        return null;
    14    }

    Spring MVC其实就是通过遍历ViewResolvers这种视图解析器集合,根据视图名来找到找到真正的物理视图【view页面】,对于普通的JSP页面,最常用到的view resolver就是InternalResourceViewResolver,它有两个属性,一个是匹配物理view的前缀,一个是后缀。前缀一般就是view页面的路径位置,后缀就是文件的格式,而前缀后缀之间的就是逻辑view名称。

    1<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    2    <property name="prefix" value="/WEB-INF/views/" />
    3    <property name="suffix" value=".jsp" />
    4</bean>
    5

    比如按照上面的配置,如果controller返回的逻辑view名称是home的话,InternalResourceViewResolver会根据这个逻辑view名home找到其对应的实际物理view:/WEB-INF/views/home.jsp。

    下面我们在看下视图解析器的定义如下,就一个方法resolveViewName,根据视图名称和Local对象得到最终的View视图

    1public interface ViewResolver {
    2    @Nullable
    3    View resolveViewName(String viewName, Locale locale) throws Exception;
    4}

    视图渲染

    如上,通过视图解析器ViewResolver 最终会得到视图View,然后会通过调用View对象的render方法来真正执行视图渲染的逻辑,View对象的定义如下

    1public interface View {
    2
    3    String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
    4
    5
    6    void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
    7            throws Exception;
    8
    9}

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

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

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

    3、JstlView是用来生成jstl页面

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

    看下View的实现逻辑AbstractView源码如下

     1    public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
    2            HttpServletResponse response) throws Exception {
    3
    4//将model和request中的参数全部放到mergedModel中  
    5Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
    6//存放头部信息 
    7        prepareResponse(request, response);
    8////将mergedModel中的参数值放到request中  
    9        renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
    10    }

    其实就根据ModelAndView和Request中的数据,加载视图,然后写入到Response中(先设置ContentType),最后输出给用户。

    微信公众号:宋坤明
    更多精彩请参考 完整版系列 请参考此博文 也可以直接关注我

    图注:宋坤明公众号

  • 相关阅读:
    css3文字单位rem 设置文字大小
    JS实现多物体width缓冲运动实例
    vs 你不得不会的调试方式
    C# 常用修饰符
    富文本编辑器tinymce
    Swagger简单实例
    marquee标签详解
    table数据跑马灯效果
    SqlServer发布订阅
    ORM概述及常用ORM框架
  • 原文地址:https://www.cnblogs.com/skm-blog/p/9219064.html
Copyright © 2020-2023  润新知