SpringMVC——处理模型数据

ModelAndView

  • 当控制器方法的返回值如果为ModelAndView,那么它既包含视图信息,也包含模型数据信息,其实如果返回String的话,他最终也会被SpringMVc转换成ModelAndView对象。

  • 添加模型数据的方法

    • ModelAndView addObject(String attributeName,Object attributeValue)
    • ModelAndView addAllObject(Map<String,?> modelMap)
  • 设置视图

    • void setView(View view)
    • void setViewName(String viewName)
  • 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Controller
@RequestMapping("/user")
public class TestController {

/**
* 利用ModelAndView来转发数据,给前端视图
* @return modelAndView
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
//创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//设置返回视图信息
modelAndView.setViewName("success");
//添加模型数据
modelAndView.addObject("message", "Hello World");
return modelAndView;
}

}

Map和Model

  • Spring MVC 在内部使用了一个org.springframework.ui.Model 接口存储模型数据

  • Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。

  • 如果方法的入参为Map或Model类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体中,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据

@SessionAttributes注解

  • 若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes,Spring MVC 将在模型中对应的属性暂存到 HttpSession 中

  • 该注解只能放在类的上面. 而不能修饰方法。

  • @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中

    • @SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。

    • @SessionAttributes(value={“user1”, “user2”}) 会将名字为user1和user2的属性添加到session对话中

    • @SessionAttributes(types={User.class, Dept.class})会将User类型和Dept类型的对象添加到会话中

    • @SessionAttributes(value={“user1”, “user2”}, types={Dept.class}) 会将名字为user1,user2还有类型为Dept的对象添加到session会话中

ModelAttribute的使用场景

  • 比如当我们要修改一个user对象的属性,但是其中ID属性的值我们不能修改,这时我们可以先从数据库中拿到这个user对象,然后再把用户发送过来的修改请求赋值给这个user对象,(前端只对除ID属性以外的属性赋值修改了)这时我们拿到的就是ID没有被修改的user对象了

  • 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   //被ModelAttribute修饰的方法会在每个目标方法执行之前被SpringMVC调用

@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模拟从数据库中获取对象
User user = new User(1, "Tom", "123456", "tom@atguigu.com", 12);
System.out.println("从数据库中获取一个对象: " + user);

map.put("user", user);
}
}

@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("修改: " + user);
return SUCCESS;
}

运行流程:

  1. ModelAttribute修饰的方法先从数据库中获取要修改的user对象,并把这个对象放入Map中,键为user

  2. SpringMVC从map中取出键为user的对象,并将用户输入的修改的值赋给这个对象的相应属性

  3. SpringMVC将这个被赋值好的对象传到目标方法的入参中

  4. 放入map的对象的键值要和目标方法第一个字母小写的String值要相同

SpringMVC 确定目标方法 POJO 类型入参的过程

  • 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.
  • 确定一个 key:

    • 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母小写

    • 若使用了 @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值.

  • 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入

    • 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到.

    • 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从HttpSession 中来获取 key 所对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常.

    • 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则 会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数

  • SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.

ModelAttribute修饰方法的入参

  • ModelAttribute修饰的POJO类型入参有个value值,SpringMVC会通过value值为key在implicitModel中查找对应的属性,若存在,则把这个属性直接赋值给目标方法入参(POJO对象)。

  • 若不存在,则SpringMVC会以value为key,POJO入参为value存入Request中

-------------本文结束感谢阅读-------------