对于MVC框架来说模型数据是最重要的,因为控制(C)是为了产生模型数据(M),而视图(V)则是为了显示渲染模型数据。通过前面的学习,我们知道SpringMVC通过@RequestMapping将请求引导到处理方法上,使用合适的方法签名将请求消息绑定到入参。方法入参绑定请求消息只是处理方法的第一步,还有更重要的任务等待完成,即根据入参执行相应的逻辑,产生模型数据,导向到特定的视图中。
如何将模型数据暴露给视图呢?SpringMVC提供了多种途径的输出模型数据,有以下几种;
一,ModelAndView
控制器的处理方法的返回值如果为ModelAndView,则其既包含视图信息也包含模型数据信息,它有七个构造方法比如下面两中
public ModelAndView(String viewName) {
this.view = viewName;
}
public ModelAndView(String viewName, String modelName, Object modelObject) {
this.view = viewName;
addObject(modelName, modelObject);
}
可以在创建对象时把返回的视图名称,数据模型传入对象当中,也可以用它的方法设置如下
ModelAndView mv=new ModelAndView();
mv.setViewName("ModelAndView");
mv.addObject("student", student);
这个方法非常简单。
二,@ModelAttribute
如果希望将方法入参对象添加到模型中,仅需在相应的入参前使用@ModelAttribute注解即可,
public String list(@ModelAttribute("teachet") Teacher teachet){
Teacher teacher = new Teacher();
teacher.setAge(24);
teacher.setId(1);
teacher.setName("json");
return "teacher/list";
}
SpringMVC将请求消息绑定到Teacher对象中,然后再以“teacher”为键将Teacher对象放到隐藏模型中,最后在视图对象list.jsp中就可以使用${teacher.name}取值显示了。
@ModelAttribute也可以在方法上使用,SpringMVC在调用目标方法前,会先逐个调用在方法级上标注了@ModelAttribute的方法,并将这些方法的返回值添加到隐藏模型中
三,ModelMap
SpringMVC在调用方法前会创建一个隐含的模型对象,作为模型数据的存储容器,我们称之为“隐含模型”,如果处理方法的入参为Map或Model,ModelMap类型,SpringMVC会将隐藏模型的引用传递给这些入参,在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性,例子
@ModelAttribute("teacher")
public Teacher list(){
Teacher teacher = new Teacher();
teacher.setAge(24);
teacher.setId(1);
teacher.setName("json");
return teacher;
}
@RequestMapping("/add")
public String add(ModelMap modeMap){
Teacher teacher =(Teacher) modeMap.get("teacher");
System.out.println(" I am add() method!--TeacherController"+teacher);
return "teacher/add";
}
SpringMVc一旦发现处理方法有Map或者Model,ModelMap类型的入参,就会把隐藏模型对象传递给这些参数,所以在方法体中可以通过这个入参对模型数据进行读写操作。
四,@SessionAttributes
如果希望多个请求之间共享某个模型数据,可以在控制器类标注@SessionAttributes,spring mvc会将模型中对应的属性暂存到httpSession中
@SessionAttributes(“user”)
public class UserController {
@ModelAttribute(“user”)
publicUser getUser(){
Useruser = new User();
User.setUserId(“1001”);
returnuser;
}
@RequestMapping(“/handle71”)
public String handle71(@ModelAttribute(“user”)User user) {
user.setName(“John”);
return “redirect:/user/handle72.html”;
}
@RequestMapping(value= "/handle72")
public String handle72(ModelMapmodelMap,SessionStatus sessionStatus) {
User user = (User)modelMap.get(“user”);
If(user!=null){
user.setName(“jetty”);
sessionStatus.setComplete();
}
return "user/showUser";
}
}
Spring mvc在调用处理方法前,在请求线程中自动一个隐含的模型对象,调用所有在方法级别标注了@ModelAttribute的方法,并将方法返回值添加到隐含模型中,查看Session中是否存在@SessionAttributes(“xxx”)所指定的xxx属性,如果有,将其添加到隐含模型中,如果隐含模型已经存在xxx属性,该步骤会覆盖隐含模型中已有的属性值。
对应标注了@ModelAttribute(“xxx”)方法的入参按如下流程
如果隐含模型包含了xxx属性,将其赋给该入参,再用请求消息填充该入参对象直接返回,否则如果xxx是会话属性,即处理类定义出标注了@SessionAttributes(“xxx”),则尝试从该会话中获取该属性,并将其值赋给入参,然后再用请求填充该入参对象,如会话中找不到xxx属性,则抛出HttpSessionRequiredException,如果隐含模型不存在xxx属性,且xxx也不是会话属性,则创建入参的对象实例,在用请求填充该入参。
@SessionAttributes 允许指定多个属性。你可以通过字符串数组的方式指定多个属性,如 @SessionAttributes({“attr1”,”attr2”})。此外,@SessionAttributes 还可以通过属性类型指定要 session 化的 ModelMap 属性,如 @SessionAttributes(types = User.class),当然也可以指定多个类,如@SessionAttributes(types = {User.class,Dept.class}),还可以联合使用属性名和属性类型指定:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,”attr2”})。
@SessionAttributes需要清除时,使用SessionStatus.setComplete();来清除。注意,它只清除@SessionAttributes的session,不会清除HttpSession的数据