在 SpringMVC 中,控制器方法的参数可以使用 Model
、ModelMap
和普通的 Map
来传递数据给视图。
Model
Model
是一个接口,用于封装控制器方法的模型数据。它允许控制器方法将数据添加到模型中,并在视图中进行访问。
用法:
- 使用
addAttribute(String name, Object value)
方法将属性添加到模型中。 - 在视图中通过
${name}
表达式访问模型中的属性。 - 注意点:
Model
接口是 SpringMVC 特定的,与 Web 技术无关。- 是一个接口,需要使用具体的实现类(如
ModelAndView
)进行操作。
示例:
@RequestMapping("/example") public String exampleMethod(Model model) { model.addAttribute("message", "Hello, World!"); return "exampleView"; }
ModelMap:
ModelMap
是 Model
接口的实现类,提供了更多的便捷方法。
用法:
- 可以使用
addAttribute(String name, Object value)
方法将属性添加到模型中。 - 在视图中通过
${name}
表达式访问模型中的属性。 - 注意点:
ModelMap
实现了Map
接口,因此具备了 Map 的特性。
示例:
@RequestMapping("/example") public String exampleMethod(ModelMap model) { model.addAttribute("message", "Hello, World!"); return "exampleView"; }
普通的 Map:
普通的 Map
是一种常规的 Java 集合,用于封装模型数据。
用法:
- 使用
put(String key, Object value)
方法将属性添加到 Map 中。 - 在视图中通过
${key}
表达式访问 Map 中的属性。 - 注意点:
- 可以使用任何类型的 Map 来传递数据,但推荐使用
Model
或ModelMap
,因为它们是 SpringMVC 框架提供的专门用于封装模型数据的类。
示例:
@RequestMapping("/example") public String exampleMethod(Map<String, Object> model) { model.put("message", "Hello, World!"); return "exampleView"; }
注意
1. 通过 Model、ModelMap 进行作用域的处理,就可以解决视图模板技术耦合的问题。
2. SpringMVC 中提供 Model 和 ModelMap 这两种方式处理 requst 作用域,他们的区别是什么?
表现形式上虽然是通过两种开发方式,声明的形参类型不同,一个是 Model,另一个是 ModelMap。但是在运行时,SpringMVC 会动态的提供对应的实现类型,名字是BindingAwareModelMap。所以本质上两者是相同的。
3. 那为什么不直接使用 BindingAwareModelMap?
在源码中 SpringMVC 不建议使用 BindingAwareModelMap。其原因是因为如果直接使用 BindingAwareModelMap 的话,会存在耦合。MVC 开发时使用 BindingAwareModelMap,而 WebFlux 开发时使用的是 ConcurrentModel。如果替换 Web 的实现方案,直接使用 BindingAwareModelMap 话,不利于项目的维护,得修改代码。所以更加建议使用 Model 接口处理。
4. SpringMVC 为什么会提供二种开发方式?Model、ModelMap 这两种开发方式那种方式更加推荐使用?
不推荐使用 ModelMap,他是 SpringMVC 2.0 引入的类型。当时的设计只是针对于 MVC 的场景使用,替换作用域。而后续 Spring 又支持了 WebFlux 的开发方式。显然使用 ModelMap 就无法使用了。所以 SpringMVC 在 2.5.1 引入了全新设计的接口 Model,他既可以兼容传统 MVC 也可以在 WebFlux 中使用。更加有利于项目维护。鉴于此更加推荐使用 Model 的方式。而 SpringMVC 为了兼容性,所以两者目前都可以使用。
5. 如果 redirect 跳转,数据该如何传递?
SpringMVC 会自动的把 Model 或者 ModelMap 中的数据,通过 ?
的形式在 url 上进行拼接,从而传递数据。我们在使用 redirect 跳转前只需要将要传递的数据放在 Model 或者 ModelMap 中即可,不需要手动拼接参数。