Spring MVC 中Model, ModelMap, ModelAndView 之间有什么关系和区别?

在 Spring MVC 中,Model, ModelMap, 和 ModelAndView 都是用来在 Controller 和 View 之间传递数据的,但它们在使用方式和功能上有所不同。

它们的核心在于:Spring MVC 需要知道两件事来渲染视图:① 数据 (Model) ② 视图名称 (View Name)

下面我们详细介绍一下它们的关系和区别:

  1. Model (接口)

    • 是什么Model 是一个接口 (org.springframework.ui.Model)。它主要用于在 Controller 方法中添加需要在 View 中展示的数据。
    • 如何工作:当我们在 Controller 方法的参数中声明一个 Model 类型的参数时,Spring MVC 会自动创建一个 Model 的实例(通常是 ExtendedModelMap 的实例)并将其传递给我们的方法。
    • 主要方法
      • addAttribute(String attributeName, Object attributeValue): 添加单个属性。
      • addAttribute(Object attributeValue): 添加属性,名称由类型推断。
      • addAllAttributes(Map<String, ?> attributes): 添加一个 Map 中的所有属性。
      • mergeAttributes(Map<String, ?> attributes): 合并一个 Map 中的属性,如果键已存在则覆盖。
      • containsAttribute(String attributeName): 检查是否存在某个属性。
    • 视图选择:当使用 Model 时,Controller 方法通常返回一个 String 类型的值,这个字符串就是逻辑视图名。Spring MVC 会根据这个视图名找到对应的视图进行渲染。
    • 示例
      @Controller
      public class MyController {@GetMapping("/showData")public String showData(Model model) {model.addAttribute("message", "Hello from Model!");User user = new User("John Doe", 30);model.addAttribute("user", user);return "dataView"; // 返回逻辑视图名}
      }
      
  2. ModelMap (类)

    • 是什么ModelMap 是一个类 (org.springframework.ui.ModelMap),它实现了 Model 接口,并且继承自 java.util.LinkedHashMap
    • 如何工作:与 Model 类似,我们可以在 Controller 方法参数中声明它,Spring MVC 会提供相应的实例。因为它是一个 Map,所以我们可以使用所有 Map 的方法(如 put(), get() 等)以及 Model 接口定义的方法。
    • Model 的关系ModelMapModel 接口的一个具体实现。当我们使用 Model 接口时,Spring MVC 内部提供的是 ModelMap(或其子类 ExtendedModelMap)的实例。
    • 视图选择:与 Model 相同,Controller 方法通常返回一个 String 类型的逻辑视图名。
    • 为什么存在
      • 提供了 Map 的便利性,如果已经有了一个 Map 对象,可以直接用 addAllAttributesputAll
      • 历史原因,在泛型广泛使用前,ModelMap 提供了类型安全(相对于直接使用 Map<String, Object>)。
    • 示例
      @Controller
      public class MyController {@GetMapping("/showDataWithModelMap")public String showDataWithModelMap(ModelMap modelMap) {modelMap.addAttribute("message", "Hello from ModelMap!");modelMap.put("anotherMessage", "Using put method!"); // Map 的方法User user = new User("Jane Doe", 25);modelMap.addAttribute("user", user);return "dataView"; // 返回逻辑视图名}
      }
      
  3. ModelAndView (类)

    • 是什么ModelAndView 是一个类 (org.springframework.web.servlet.ModelAndView),它是一个容器,同时持有 模型数据 (Model)视图信息 (View)
    • 如何工作:与 ModelModelMap 不同,ModelAndView 对象是由我们在 Controller 方法中创建并返回的。我们不需要将其声明为方法参数(虽然也可以,但不常见)。
    • 主要方法/构造函数
      • ModelAndView(String viewName)
      • ModelAndView(String viewName, Map<String, ?> model)
      • ModelAndView(String viewName, String modelName, Object modelObject)
      • addObject(String attributeName, Object attributeValue): 添加模型数据。
      • setViewName(String viewName): 设置逻辑视图名。
      • setView(View view): 直接设置一个 View 对象。
      • getModel(): 获取模型数据 (返回一个 Map)。
      • getModelMap(): 获取模型数据 (返回一个 ModelMap)。
    • 视图选择:视图信息直接包含在 ModelAndView 对象中。
    • 示例
      @Controller
      public class MyController {@GetMapping("/showDataWithModelAndView")public ModelAndView showDataWithModelAndView() {ModelAndView mav = new ModelAndView();mav.setViewName("dataView"); // 设置逻辑视图名mav.addObject("message", "Hello from ModelAndView!");User user = new User("Peter Pan", 100);mav.addObject("user", user);return mav; // 返回 ModelAndView 对象}
      }
      

关系总结

  • Model 是一个接口,定义了添加数据到模型的基本操作。
  • ModelMapModel 接口的一个实现,它本身是一个 LinkedHashMap,提供了 Map 的操作便利性。
  • ModelAndView 是一个独立的类,它封装了模型数据(内部使用 ModelMap 或类似的 Map 结构来存储数据)和视图信息。

区别总结

特性Model (接口)ModelMap (类)ModelAndView (类)
类型接口类 (实现 Model, 继承 LinkedHashMap)
主要职责仅传递数据仅传递数据 (以 Map 形式)传递数据 指定视图
如何获取实例作为 Controller 方法参数 (Spring 注入)作为 Controller 方法参数 (Spring 注入)在 Controller 方法中 new 出来并返回
视图指定Controller 方法返回 String 视图名Controller 方法返回 String 视图名视图名或 View 对象在 ModelAndView 内部设置
返回值String (逻辑视图名)String (逻辑视图名)ModelAndView 对象本身
灵活性专注于数据,视图名解耦专注于数据,视图名解耦,有 Map 特性数据和视图紧密耦合在一个对象中

使用场景?

  • Model (推荐)

    • 这是目前最常用和推荐的方式。
    • 当 Controller 方法的主要职责是准备数据,并且视图名是固定的或者可以通过简单的字符串返回时。
    • 代码更简洁,职责分离更清晰(方法只关注数据,返回类型指明视图)。
  • ModelMap

    • 如果需要 Map 的特定方法,或者想强调模型数据是一个 Map 结构时。
    • 实际上,由于 Model 接口已经足够强大,并且 Spring 内部通常用 ModelMap 的子类 ExtendedModelMap 来实现 Model,所以直接使用 Model 接口通常更好。
  • ModelAndView

    • 当 Controller 方法需要根据逻辑动态决定返回哪个视图,或者需要返回一个具体的 View 对象时。
    • 在一些较早的 Spring MVC 代码中比较常见。
    • 当你想将数据和视图信息明确的捆绑在一起返回时。
    • 如果你需要返回 null 来指示不渲染任何视图(例如,在某些拦截器或特殊处理中),ModelAndView 也可以做到(返回 nullModelAndView)。

Spring MVC 实践建议:

优先使用 Model 作为方法参数,并让 Controller 方法返回 String 类型的逻辑视图名。这种方式更简洁,也更符合 Spring MVC 的设计,即 Controller 负责处理请求、准备数据,并将逻辑视图名交给 ViewResolver 去解析。

只有在确实需要将模型和视图紧密绑定,或者需要动态决定视图对象本身时,考虑使用 ModelAndViewModelMap 的使用场景相对较少,通常 Model 接口就能满足需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置Hadoop集群-免密登录

在 Hadoop 集群中配置免密登录是确保各节点间高效通信的关键步骤。以下是基于 SSH 密钥认证的免密登录配置方案&#xff0c;支持主节点&#xff08;NameNode&#xff09;到所有从节点&#xff08;DataNode&#xff09;的无密码访问&#xff1a; 1. 环境准备 集群规划&#xff…

C++类与对象(二):六个默认构造函数(一)

在学C语言时&#xff0c;实现栈和队列时容易忘记初始化和销毁&#xff0c;就会造成内存泄漏。而在C的类中我们忘记写初始化和销毁函数时&#xff0c;编译器会自动生成构造函数和析构函数&#xff0c;对应的初始化和在对象生命周期结束时清理资源。那是什么是默认构造函数呢&…

嵌入式培训之数据结构学习(一)数据结构的基础概念、线性表

一、基础概念 1、数据结构&#xff1a;相互之间存在一种或多种特定关系的数据元素的集合。&#xff08;特定关系有逻辑关系与线性关系&#xff09; &#xff08;1&#xff09;逻辑结构 集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等&#xff08;数组&#xff…

Android Exoplayer 实现多个音视频文件混合播放以及音轨切换

在之前的文章ExoPlayer中常见MediaSource子类的区别和使用场景中介绍了Exoplayer中各种子MediaSource的使用场景&#xff0c;这篇我们着重详细介绍下实现多路流混合播放的用法。常见的使用场景有&#xff1a;视频文件电影字幕、正片视频广告视频、背景视频背景音乐等。 初始化…

推特逆向算法,推特爬虫,数据分析,推特关键词搜索

祝大家五一假期快乐&#xff01; 最近推特加了逆向&#xff0c;频繁出现404&#xff0c;无法正常抓取数据&#xff0c;这里给出推特逆向的思路及代码&#xff0c;供大家参考学习&#xff01; 本文将介绍如何使用 Python 模拟请求 Twitter 的 GraphQL 接口&#xff0c;结合 re…

图形化编程平台的破局之道:从工具同质化到生态差异化

一、同质化困局的底层逻辑剖析 在全球图形化编程市场中&#xff0c;工具功能趋同已成为行业共识。据 Statista 2024 年数据显示&#xff0c;主流平台的基础功能重合度高达 78%&#xff0c;核心模块&#xff08;如条件判断、循环结构&#xff09;的实现方式高度相似。这种现象的…

【Rust】枚举和模式匹配

目录 枚举和模式匹配枚举的定义Option 枚举控制流运算符 match简洁控制流 if let 枚举和模式匹配 枚举的定义 结构体给予你将字段和数据聚合在一起的方法&#xff0c;像 Rectangle 结构体有 width 和 height 两个字段。而枚举给予你一个途径去声明某个值是一个集合中的一员。…

应急响应靶机——WhereIS?

用户名及密码&#xff1a;zgsf/zgsf 下载资源还有个解题.exe: 1、攻击者的两个ip地址 2、flag1和flag2 3、后门程序进程名称 4、攻击者的提权方式(输入程序名称即可) 之前的命令&#xff1a; 1、攻击者的两个ip地址 先获得root权限&#xff0c;查看一下历史命令记录&#x…

变量函数实战:高保真APP原型“发票页面”动态交互教程

变量函数是高保真交互原型设计中常见的高级交互功能&#xff0c;能够避免重复复制与手动修改页面元素和逻辑标注&#xff0c;让演示更有真实体验感。本文分享一个高保真APP交互原型页面的实操案例&#xff0c;结合原型设计工具中的变量函数与逻辑判断功能&#xff0c;手把手教你…

量子加密通信:守护信息安全的未来之盾

摘要 在数字化时代&#xff0c;信息安全成为全球关注的焦点。传统加密技术面临着被量子计算破解的风险&#xff0c;而量子加密通信作为一种基于量子力学原理的新型加密技术&#xff0c;提供了理论上无条件安全的通信保障。本文将详细介绍量子加密通信的基本原理、技术实现、应用…

《Vue.js》阅读之响应式数据与副作用函数

Vue.js 《Vue.js设计与实现》&#xff08;霍春阳&#xff09; 适合&#xff1a;从零手写Vue3响应式系统&#xff0c;大厂面试源码题直接覆盖。重点章节&#xff1a;第4章&#xff08;响应式&#xff09;、第5章&#xff08;渲染器&#xff09;、第8章&#xff08;编译器&…

数据处理专题(十三)

学会基本的图像处理技术。‍ OpenCV 基础 实践&#xff1a;使用 OpenCV 进行图像读取、显示和基本处理‍ 03 代码示例 1. 导入必要的库 import cv2import numpy as npimport matplotlib.pyplot as plt 2. 图像读取 # 读取图像image_path path_to_your_image.jpg # 替换…

springboot旅游小程序-计算机毕业设计源码76696

目 录 摘要 1 绪论 1.1研究背景与意义 1.2研究现状 1.3论文结构与章节安排 2 基于微信小程序旅游网站系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统…

P1874 快速求和

目录 题目算法标签: 动态规划, 线性 d p dp dp思路代码 题目 P1874 快速求和 算法标签: 动态规划, 线性 d p dp dp 思路 求的是最少组成 n n n的加法次数, 对于当前数字序列可以设计状态表示 f [ i ] [ j ] f[i][j] f[i][j]表示考虑前 i i i个字符, 并且和是 j j j的所有方…

知名人工智能AI培训公开课内训课程培训师培训老师专家咨询顾问唐兴通AI在金融零售制造业医药服务业创新实践应用

AI赋能未来工作&#xff1a;引爆效率与价值创造的实战营 AI驱动的工作革命&#xff1a;从效率提升到价值共创 培训时长&#xff1a; 本课程不仅是AI工具的操作指南&#xff0c;更是面向未来的工作方式升级罗盘。旨在帮助学员系统掌握AI&#xff08;特别是生成式AI/大语言模型…

Linux 内核参数

文章目录 什么是内核参数参数种类配置方式1. 编译内核时配置2. 内核启动时配置3. 内核运行时配置4. 加载内核模块时配置总结 什么是内核参数 内核参数是 Linux 系统中用于控制和调整内核行为的可配置选项。这些参数影响系统的性能、安全性和各种功能特性。 参数种类 大部分参…

pythonocc 拉伸特征

micromamba install -c conda-forge pythonocc-core opencascade.js安装不起来&#xff0c;ai用pythonocc练个手 拉伸线框 线成面 from OCC.Core.gp import gp_Pnt, gp_Dir, gp_Vec from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeWire f…

Vue.js 页面切换空白与刷新 404 问题深度解析

在使用 Vue.js 开发单页应用 (SPA) 的过程中&#xff0c;开发者经常会遇到两个常见问题&#xff1a;页面切换时出现短暂的空白屏幕&#xff0c;以及刷新页面时返回 404 错误。这两个问题不仅影响用户体验&#xff0c;还可能阻碍项目的正常上线。本文将深入探讨这两个问题的成因…

Go 语言 slice(切片) 的使用

序言 在许多开发语言中&#xff0c;动态数组是必不可少的一个组成部分。在实际的开发中很少会使用到数组&#xff0c;因为对于数组的大小大多数情况下我们是不能事先就确定好的&#xff0c;所以他不够灵活。动态数组通过提供自动扩容的机制&#xff0c;极大地提升了开发效率。这…

Qt5.14.2 链接 MySQL 8.4 遇到的问题

问题一: "Plugin caching_sha2_password could not be loaded: 找不到指定的模块。 Library path is caching_sha2_password.dll QMYSQL: Unable to connect" 解决方法: alter user root@localhost identified with mysql_native_password by root;问题二: ERR…