zoukankan      html  css  js  c++  java
  • springMVC4(7)模型视图方法源代码综合分析

    在完整web开发中。springMVC主要充当了控制层的角色。它接受视图层的请求。获取视图层请求数据,再对数据进行业务逻辑处理。然后封装成视图层须要的模型数据,再将数据导向到jsp等视图界面。
    在前面,我们通过对@RequestMapping和方法入參绑定的分析,完毕了视图层->控制层的数据交接,然后业务逻辑处理主要由Service层进行。那么接下来非常关键的就是,怎样将视图数据导向到特定的视图中。

    广泛意义上,视图,并不是是单指前端界面如jsphtml等。我们可能须要给安卓、IOS等写后台接口、因前后端分离而放弃视图界面导向如对前端ajax请求的纯数据流输出等。

    这时,我们的视图能够为json视图、xml视图、乃至PDF视图、Excel视图等

    springMVC为我们提供了多种途径输出模型数据:

    输出途径 功能说明
    ModelAndView 将处理方法返回类型设为ModelAndView。里面封装了我们的模型数据,同一时候指明了视图导向。

    @modelAttribute 方法入參标注改注解后,入參的对象就会放到数据模型中。

    Map及Model 入參为org.springframework.ui.Model或org.springframework.ui.ModelMap或java.util.Map时,方法返回时会将Map中的数据自己主动加入到模型中
    @SessionAttributes 将模型中的某个属性暂存到HttpSession中,以便多个请求之间完毕属性共享

    以下我们主要介绍ModelAndView
    ModelAndView(以下简称MAV)就像它的名字一样。既包括了模型数据又包括视图信息。我们返回一个MAV。springMVC就会将模型数据转发给相应的视图界面。
    在学习ModelAndView的用法前。我们先用肢解的方法学习其两个重要组成部分

    1. model

    model是一个接口,我们能够简单地将model的实现类理解成一个Map,将模型数据以键值对的形式返回给视图层使用。在springMVC中,每一个方法被前端请求触发调用前,都会创建一个隐含的模型对象,作为模型数据的存储容器。

    这是一个Request级别的模型数据。我们能够在前端页面如jsp中通过HttpServletRequest等相关API读取到这些模型数据。
    在model中。定义有例如以下经常使用接口方法:

        /**
         * 加入键值属性对
         */
        Model addAttribute(String attributeName, Object attributeValue);
    
        /**
         * 以属性的类型为键加入属
         */
        Model addAttribute(Object attributeValue);
    
        /**
         * 以属性和集合的类型构造键名加入集合属性,假设有同类型会存在覆盖现象
         */
        Model addAllAttributes(Collection<?> attributeValues);
    
        /**
         * 将attributes中的内容拷贝到当前的model中
         * 假设当前model存在同样内容。会被覆盖
         */
        Model addAllAttributes(Map<String, ?> attributes);
    
        /**
         * 将attributes中的内容拷贝到当前的model中
         * 假设当前model存在同样内容,不会被覆盖
         */
        Model mergeAttributes(Map<String, ?> attributes);
    
        /**
         * 推断是否有相应的属性值
         */
        boolean containsAttribute(String attributeName);
    
        /**
         * 将当前的model转换成Map
         */
        Map<String, Object> asMap();

    假设我们加入的属性没有指定键名。我们称之为匿名数据绑定,它们遵循例如以下规则:
    1. 对于普通数据类型,我们直接以类型(第一字母小写)作为键值
    2. 对于集合类型(Collection接口的实现者们,包括数组),生成的模型对象属性名为“简单类名(首字母小写)”+“List”,如List生成的模型对象属性名为“stringList”,List生成的模型对象属性名为“userModelList”。

    在ModelAndView中,我们很多其它的是直接操作modelMap和Map来完毕我们的模型參数准备就可以。modelMap继承自java.util.LinkedHashMap。

    它在LinkedHashMap的基础上,新增了非常多便利的构造方法如:

    public ModelMap(String attributeName, Object attributeValue) {
        addAttribute(attributeName, attributeValue);
    }
    public ModelMap addAllAttributes(Map<String, ?

    > attributes) { if (attributes != null) { putAll(attributes); } return this; }

    使用这些构造方法能进一步简化我们的模型数据封装。

    2. view

    view也是一个接口,它表示一个响应给用户的视图如jsp文件,pdf文件,html文件。


    它有两个接口方法:
    1. String getContentType():返回视图的内容类型
    2. void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception:依据给定模型和web资源定义视图的渲染形式。


    view接口有众多的实现类,例如以下图所看到的:
    这里写图片描写叙述
    在spring中。通过ViewResolver来解析相应View实例的行为。 它的定义相当简单:

    public interface ViewResolver {
        //通过view name 解析View
        View resolveViewName(String viewName, Locale locale) throws Exception;
    }

    spring为我们提供ViewResolver实现类用来解析不同的view:
    这里写图片描写叙述
    在我们最開始配置springMVC核心文件时,就用到了InternalResourceViewResolver,它是一个内部资源视图解析器。

    会把返回的视图名称都解析为 InternalResourceView 对象。 InternalResourceView 会把 Controller 处理器方法返回的模型属性都存放到相应的 request 属性中。然后通过 RequestDispatcher 在server端把请求 forword 重定向到目标 URL。

    以下我们来看配置实例:

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property><!-- 前缀,在springMVC控制层处理好的请求后,转发配置文件夹下的视图文件 -->
        <property name="suffix" value=".jsp"></property><!-- 文件后缀,表示转发到的视图文件后缀为.jsp -->
    </bean>

    解析完Model and(和) View后,再来看我们的ModelAndView:

    public class ModelAndView {
    
        //视图成员
        private Object view;
    
    
        //模型成员
        private ModelMap model;
    
        //是否调用clear()方法清空视图和模型
        private boolean cleared = false;
    
    
        /**
         * 空构造方法
         */
        public ModelAndView() {
        }
    
        /**
         * 简便地使用视图名生成视图,详细解析由DispatcherServlet的视图解析器进行
         */
        public ModelAndView(String viewName) {
            this.view = viewName;
        }
    
        /**
         * 指定一个视图对象生成视图
         */
        public ModelAndView(View view) {
            this.view = view;
        }
    
        /**
         * 指定视图名同一时候绑定模型数据。这里模型数据以追加的形式加入在原来的视图数据中
         */
        public ModelAndView(String viewName, Map<String, ?

    > model) { this.view = viewName; if (model != null) { getModelMap().addAllAttributes(model); } } /** * 指定一个视图对象同一时候绑定模型数据。这里模型数据以追加的形式加入在原来的视图数据中 */ public ModelAndView(View view, Map<String, ?> model) { this.view = view; if (model != null) { getModelMap().addAllAttributes(model); } } /** * 简便配置:指定视图名,同一时候加入单个属性 */ public ModelAndView(String viewName, String modelName, Object modelObject) { this.view = viewName; addObject(modelName, modelObject); } /** * 简便配置:指定一个视图对象,同一时候加入单个属性 */ public ModelAndView(View view, String modelName, Object modelObject) { this.view = view; addObject(modelName, modelObject); } /** * 设置当前视图名 */ public void setViewName(String viewName) { this.view = viewName; } /** * 获取视图名。假设当前视图属性为view而非名字(String)则返回null */ public String getViewName() { return (this.view instanceof String ? (String) this.view : null); } /** * 设置当前视图对象 */ public void setView(View view) { this.view = view; } /** * 获取视图,假设非view实例,则返回null */ public View getView() { return (this.view instanceof View ? (View) this.view : null); } /** * 推断当前视图是否存在 */ public boolean hasView() { return (this.view != null); } /** * 获取模型Map。假设为空,则新建一个 */ public ModelMap getModelMap() { if (this.model == null) { this.model = new ModelMap(); } return this.model; } /** * 同getModelMap */ public Map<String, Object> getModel() { return getModelMap(); } /** * 加入单个键值对属性 */ public ModelAndView addObject(String attributeName, Object attributeValue) { getModelMap().addAttribute(attributeName, attributeValue); return this; } /** * 以属性类型为键加入属性 */ public ModelAndView addObject(Object attributeValue) { getModelMap().addAttribute(attributeValue); return this; } /** * 将Map中的全部属性加入到成员属性ModelMap中 */ public ModelAndView addAllObjects(Map<String, ?> modelMap) { getModelMap().addAllAttributes(modelMap); return this; } /** * 清空视图模型。并设为清空状态 */ public void clear() { this.view = null; this.model = null; this.cleared = true; } /** * 推断是否为不含视图和模型 */ public boolean isEmpty() { return (this.view == null && CollectionUtils.isEmpty(this.model)); } }

  • 相关阅读:
    django之--模型层(ORM语法)
    mysql问题记录
    CentOS系统内存使用问题(内存是拿来用的,而不是拿来看的)
    CentOS6&CentOS7安装FFmpeg
    django之--模板层
    Django之--视图层
    Django之ORM学习2--路由层
    Django之ORM学习
    Django入门
    第二版mq 数据结构选型
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7402880.html
Copyright © 2011-2022 走看看