5、处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
-
ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
-
Map 及 Model: 入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
-
@SessionAttributes: 将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性
-
@ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
(1)ModelAndView
-
控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
-
添加模型数据:
MoelAndView addObject(String attributeName, ObjectattributeValue)
ModelAndView addAllObject(Map<String, ?> modelMap) -
设置视图:
void setView(View view)
void setViewName(String viewName)
SpringMVCTest.java
/*
目标方法的返回值可以是 ModelAndView 类型
其中可以包含视图和模型信息
SpringMVC 会把 ModelAndView 的 model 中数据放入到 request 域对象中。
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView(viewName);
// 添加模型数据到 ModelAndView 中
modelAndView.addObject("time", new Date());
return modelAndView;
}
index.jsp
<a href="springmvc/testModelAndView">Test ModelAndView</a>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>Success Page</h4>
time:${requestScope.time}
</body>
</html>
(2)Map 及 Model
Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据
具体步骤
- Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
- 如果方法的入参为 Map 或 Model 类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据。
SpringMVCTest.java
/*
目标方法可以添加 Map(实际上也可以是 Model 类型或 ModelMap 类型)类型的参数。
*/
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map) {
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom","Jerry","Mile"));
return SUCCESS;
}
index.jsp
<a href="springmvc/testMap">Test Map</a>
(3)@SessionAttributes
- 若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。
- @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上是 value 属性值),还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
@SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”})
@SessionAttributes(types={User.class, Dept.class})
@SessionAttributes(value={“user1”, “user2”},types={Dept.class})
- 注意:该注解只能放在类的上面,而不能修饰方法。
SpringMVCTest.java
@SessionAttributes(value={
"user"}, types = {
String.class})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map<String, Object> map){
User user = new User("Tom","123456","tom@qq.com",15);
map.put("user", user);
map.put("school","atguigu");
return SUCCESS;
}
}
index.jsp
<a href="springmvc/testSessionAttributes">Test SessionAttributes</a>
success.jsp
request user:${requestScope.user}
<br><br>
session user:${sessionScope.user}
<br><br>
request school:${requestScope.school}
<br><br>
session school:${sessionScope.school}
(4)@ModelAttribute
-
在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了 @ModelAttribute 的方法。
-
@ModelAttribute 注解也可以来修饰目标方法 POJO 类型的入参,其 value 属性值有如下的作用:
①SpringMVC 会使用 value 属性值在 implicitModel 中查找对应的对象,若存在则会直接传入到目标方法的入参中。
②SpringMVC 会以 value 为 key,POJO 类型的对象为 value,存入到 request 中 -
在方法的入参前使用 @ModelAttribute 注解:
可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参。
将方法入参对象添加到模型中
SpringMVCTest.java
/*
有 @ModelAttribute 标记的方法,会在每个目标方法执行之前被 SpringMVC 调用!
*/
@ModelAttribute
public void getUser(@RequestParam(value = "id",required = false) Integer id,Map<String,Object> map){
if (id != null) {
// 模拟从数据库中获取对象
User user = new User(1,"Tom","123456","tom.@qq.com",12);
System.out.println("从数据库中获取一个对象:" + user);
map.put("user",user);
}
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("修改:" + user);
return SUCCESS;
}
index.jsp
<%--
模拟修改操作
1.原始数据为:1,Tom,123456,tom@qq.com,12
2.密码不能被修改
3.表单回显,模拟操作直接在表单填写对于的属性值
--%>
<form action="springmvc/testModelAttribute" method="post">
<input type="hidden" name="id" value="1" />
username:<input type="text" name="username" value="Tom"/>
<br>
email:<input type="text" name="email" value="tom@qq.com"/>
<br>
age:<input type="text" name=