当前位置: 首页 > news >正文

Spring MVC中Controller是如何把数据传递给View的?

在 Spring MVC 中,Controller 负责请求的处理,准备需要展示的数据,并将这些数据传递给 View,由 View 负责最终的页面渲染。数据从 Controller 传递到 View 主要通过模型 (Model) 实现。

Spring MVC 提供了以下几种方式让 Controller 将数据添加到模型中,然后将模型传递给视图:

  1. 使用 Model 接口作为 Controller 方法参数 (推荐)

    • 这是目前最常用和推荐的方式。可以在 Controller 方法的参数列表中声明一个 org.springframework.ui.Model 类型的参数。
    • Spring MVC 在调用方法时会自动创建一个 Model 实例并将其传递给方法。
    • 可以使用 model.addAttribute(key, value) 方法向模型中添加属性,其中 key 是属性名(字符串),value 是要传递的数据对象。View 将使用这个 key 来访问数据。
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;@Controller
    public class UserController {@GetMapping("/greeting")public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {// 准备数据String message = "Hello, " + name + "!";// 将数据添加到模型中,key 是 "greetingMessage"model.addAttribute("greetingMessage", message);model.addAttribute("pageTitle", "Greeting Page"); // 可以添加多个属性// 返回视图名return "greetingView"; // Spring MVC 会找到名为 greetingView 的视图来渲染}
    }
    

    greetingView 这个视图(例如 JSP, Thymeleaf 模板等)中,我们可以通过 greetingMessagepageTitle 这两个 key 来访问模型中的数据。

  2. 使用 MapModelMap 作为 Controller 方法参数

    • ModelMapLinkedHashMap 的子类,也实现了 Map 接口,提供了与 Model 相似的功能 (addAttribute 方法)。
    • Map 接口也可以直接使用。
    • 它们的行为与 Model 接口基本相同,都是向模型中添加键值对数据。
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import java.util.Map;@Controller
    public class ProductController {@GetMapping("/productDetails")public String showProductDetails(Map<String, Object> model) {// 准备数据Product product = productService.getProductById(123L);// 将数据添加到 Map (模型) 中model.put("product", product);model.put("currency", "USD");// 返回视图名return "productDetailsView";}
    }
    

    productDetailsView 视图中,可以通过 productcurrency 访问数据。

  3. 使用 ModelAndView 返回值

    • ModelAndView 是 Spring MVC 早期常用的类,它将模型数据和视图名封装在一个对象中返回。
    • 通过 addObject(key, value) 添加模型数据,通过 setViewName(viewName) 设置视图名。
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.servlet.ModelAndView;@Controller
    public class OrderController {@GetMapping("/orderDetails")public ModelAndView showOrderDetails() {// 准备数据Order order = orderService.getOrderById(456L);// 创建 ModelAndView 对象ModelAndView mav = new ModelAndView();// 添加模型数据mav.addObject("order", order);mav.addObject("status", "Shipped");// 设置视图名mav.setViewName("orderDetailsView");return mav;}
    }
    

    orderDetailsView 视图中,可以通过 orderstatus 访问数据。

  4. 使用 @ModelAttribute 标注方法

    • 可以在 Controller 类中定义一个方法,并使用 @ModelAttribute 标注它。
    • 这个方法会在 Controller 的请求处理方法执行之前被调用。
    • 该方法的返回值(通过参数 Model 添加的数据)会自动添加到模型中,供当前 Controller 的所有方法以及最终的视图使用。常用于添加一些公共的、所有视图都需要的数据(如导航信息、用户登录状态等)。
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ModelAttribute;@Controller
    public class CommonDataController {// 这个方法会在每次处理请求前执行@ModelAttributepublic void addCommonData(Model model) {model.addAttribute("appName", "My Awesome App");model.addAttribute("currentUser", "Guest"); // 实际应用中这里会获取当前登录用户}@GetMapping("/home")public String homePage() {// homeView 视图可以直接访问 appName 和 currentUserreturn "homeView";}@GetMapping("/about")public String aboutPage() {// aboutView 视图也可以访问 appName 和 currentUserreturn "aboutView";}
    }
    

    homeViewaboutView 中,都可以访问 appNamecurrentUser

  5. 通过 Controller 方法的返回值 (当返回值不是 String, View, ModelAndView 等特殊类型时)

    • 如果 Controller 方法返回一个 POJO 对象,并且没有 @ResponseBody 注解,Spring MVC 会尝试将这个返回值也添加到模型中。默认情况下,属性名会根据返回值的类型自动生成(例如,返回 User 对象,属性名可能是 “user” 或 “aUser”)。

数据如何到达 View?

当 Controller 方法执行完毕,Spring MVC 会将模型中的数据(通常存储在一个 MapModelMap 对象中)放入到请求属性 (Request Attributes) 中。然后,Spring MVC 将控制权交给选定的 View。

不同的 View 技术访问请求属性的方式不同:

  • JSP/JSTL/EL (Expression Language): 可以直接使用 EL 表达式访问模型中的属性,例如 ${greetingMessage}${user.name}
  • Thymeleaf: 使用 OGNL 或 Spring EL 表达式,例如 <p th:text="${greetingMessage}"></p><span th:text="${product.price}"></span>
  • Freemarker: 使用 ${greetingMessage}${user.name}

总结传递数据的过程:

  1. Controller 通过 ModelMapModelAndView@ModelAttribute 方法将数据以键值对的形式添加到 Spring 管理的模型中。
  2. Spring MVC 在处理请求的后期,将模型中的数据复制到当前请求的属性中 (HttpServletRequest 的属性)。
  3. Spring MVC 委托 ViewResolver 找到对应的 View(例如 JSP 文件)。
  4. View 引擎(例如 JSP 容器、Thymeleaf 引擎)在渲染页面时,可以从请求属性中获取到 Controller 放入的模型数据,并将其呈现在最终的 HTML 或其他格式的响应中。

选择哪种方式取决于具体使用场景。使用 Model 参数是最灵活的方式,它将模型的管理与视图名分开来返回,使 Controller 方法更清晰。ModelAndView 适合模型数据和视图名紧密关联、一起返回的场景。@ModelAttribute 适合跨多个请求处理的公共数据。

http://www.xdnf.cn/news/318565.html

相关文章:

  • 自由浮动时间和总浮动时间对比
  • 学习整理使用php将SimpleXMLElement 对象解析成数组格式的方法
  • 『深夜_MySQL』数据库操作 字符集与检验规则
  • 桥接模式(Bridge)
  • 从 “机器人 +“ 到 “+ 机器人“:算力政策撬动的产业生态革命
  • 针对Mkdocs部署到Githubpages加速访问速度的一些心得
  • Flutter TabBar / TabBarView 详解
  • 蓝桥杯青少 图形化编程——“星星”点灯
  • hadoop中的序列化和反序列化(2)
  • 软件开发各阶段的自动化测试技术详解
  • 好的软件系统
  • 3、Kafka 核心架构拆解和总结
  • 线程池技术
  • mongodb 学习笔记
  • Java泛型
  • PyTorch 中如何针对 GPU 和 TPU 使用不同的处理方式
  • CPU的基本认识
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】7.2 PostgreSQL与Python数据交互(psycopg2库使用)
  • 解决HomeAssistant 无法安装 samba share问题
  • C++ set和map系列(关联式容器)的介绍及使用
  • 如何有效防御服务器DDoS攻击
  • GoFly企业版框架升级2.6.6版本说明(框架在2025-05-06发布了)
  • 【macOS】iTerm2介绍
  • 21. LangChain金融领域:合同审查与风险预警自动化
  • 直线最小二乘法线性拟合-- points点集合
  • 【JS逆向基础】并发爬虫
  • 01Introduction
  • Flowable7.x学习笔记(二十一)查看我的发起
  • uniapp 搭配 uCharts
  • 禁止idea联网自动更新通过防火墙方式