当前位置: 首页 > 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 适合跨多个请求处理的公共数据。

相关文章:

  • 2025ISCC练武校级赛部分题解WP
  • (1-1)Java的JDK、JRE、JVM三者间的关系
  • 可视化魔法指南
  • 如何检查 Watchtower 是否正常工作及更新未生效的排查方法【日常排错】
  • C语言学习之字符函数和字符串函数
  • 2025年五一假期旅游市场新趋势:理性消费、多元场景与科技赋能
  • C#管道通讯及传输信息丢失的原因
  • 信息革命对经济、货币体系及权力结构的颠覆性影响
  • 深入了解linux系统—— 进程控制
  • 虚拟现实(VR)与增强现实(AR)在教育领域的应用:开启沉浸式学习新时代
  • 006 yum和Linux生态
  • 可执行文件格式(ELF格式)以及进程地址空间第二讲【Linux操作系统】
  • 精益数据分析(46/126):深入剖析用户生成内容(UGC)商业模式
  • 各地级市儒家学校、学堂、孔庙数据
  • sizeof 和 strlen 的区别
  • 链表——C语言
  • Nacos源码—5.Nacos配置中心实现分析一
  • 多功能气体检测报警系统,精准监测,守护安全
  • 数据结构——排序(万字解说)初阶数据结构完
  • Java学习手册:ORM 框架性能优化
  • 4月证券私募产品备案量创23个月新高,股票策略占比超六成
  • 西安机场回应航站楼“水帘洞”事件:屋面排水系统被冰雹堵塞
  • 大四本科生已发14篇SCI论文?重庆大学:成立工作组核实
  • 追光|铁皮房、土操场,这有一座“筑梦”摔跤馆
  • 乌克兰议会批准美乌矿产协议
  • 水利部:山西、陕西等地旱情将持续