1. 模型数据
springmvc 提供了以下几种途径输出模型数据:
- ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据
- Map及Model:入参为Model、ModelMap、Map,处理方法返回时,Map中的数据会自动添加到模型数据中
- @SessionAttribute:将模型数据暂存到HttpSession中,以便多个请求之间可以共享这个属性
- @ModelAttribute:方法入参标注该注解后,入参的对象就会放到数据模型中
1.1ModelAndView
- 控制器处理方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型数据信息
- 添加模型数据
ModelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map<String, ?> modelMap) - 设置视图
void setView(View view)
void setViewName(String viewName)
后台:
使用构造方法添加视图
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
String viewName = SUCCESS;
// 1.设置视图(通过构造器)
ModelAndView modelAndView = new ModelAndView(viewName);
// 2.添加模型数据
modelAndView.addObject("time", new Date());
return modelAndView;
}
或者使用setter()方法添加视图
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView();
// 1.添加模型数据
modelAndView.addObject("time", new Date());
//2.使用setter()方法添加视图
modelAndView.setViewName(viewName);
return modelAndView;
}
springmvc会把ModelAndView的model中数据放入到request域中
前端访问:
<a href="test/testModelAndView">testModelAndView</a>
跳转页面success.jsp
<body>
<h1>SUCCESS</h1>
${time}
</body>
获取了之前添加的数据模型time的值
1.2Map及Model
- springmvc在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器
- 如果方法的入参为Map/Model类型,springmvc会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的素有数据,也可以向模型中添加新的属性数据
后台
使用Map
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map) {
map.put("names", Arrays.asList("Tom", "Andy"));
return SUCCESS;
}
往Map中添加了一个key为names,值为:{tom, andy}
或者使用Model
@RequestMapping("/testMap")
public String testMap(Model model) {
model.addAttribute("names", Arrays.asList("Tom", "Andy"));
return SUCCESS;
}
前端访问
<a href="test/testMap">testMap</a><br>
success.jsp页面获取map
<body>
<h1>SUCCESS</h1>
${names }
</body>
1.3@SessionAttribute(标注在类上)
- @SessionAttribute除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中
@SessionAttribute(type=User.class):会将隐含模型中类型为User.class的属性添加到会话中
@SessionAttribute(type={User.class, Emp.class}):
@SessionAttribute(value={“user1”, “user2”})
@SessionAttribute(value={“user1”, “user2”}, type=Emp.class)
@Controller
@RequestMapping("/test")
@SessionAttributes(value="user")
public class TestController {
private static final String SUCCESS = "success";
@RequestMapping("/testSession")
public String testSession() {
User user = new User();
return SUCCESS;
}
...
}
则user被放在session域中
1.4@ModelAttribute
应用场景:当我们修改数据时,用form表单提交,后台用相应的POJO接收,但我们想让其中一个字段不变,如:密码password。我们一旦用POJO接收后,如果传过来的字段没有password,则会自动为此POJO对象的属性password赋值为null。但我们只是想要它不变。所以,我们需要用先从数据库获取此对象属性对应的数据
前端form表单
<form action="test/testModelAttribute" method="post">
<input type="hidden" name="id" value="1" />
UserName:<input type="text" name="username" value="zzc" />
Province:<input type="text" name="address.province" value="Hubei" />
City:<input type="text" name="address.city" value="WuHan" />
<input type="submit" value="提交" />
</form>
原始数据:
name:zzc
password:123456
province:Hubei
city:WuHan
后台:
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println(user);
return SUCCESS;
}
打印结果发现:
password==null,这不是我们想要的结果
修改:
// 1.模拟从数据库中获取数据
@ModelAttribute
public void getUser(@RequestParam(value="id", required=false) Integer id,
Map<String, Object> map) {
if(null != id) {
User u = new User();
u.setUsername("zzc");
u.setPassword("123456");
Address address = new Address();
address.setProvince("Hubei");
address.setCity("WuHan");
u.setAddress(address);
map.put("user", u);
}
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println(user);
return SUCCESS;
}
在getUser()方法上添加@ModelAttribute注解。然后就能达到预期的要求了
有@ModelAttribute标记的方法,会在每个目标方法执行之前被springmvc调用
运行流程:
- 执行@ModelAttribute注解修饰的方法 :从数据库取出数据;把对象放入map中,其中k=user
- springmvc从map中取出User对象,并把表单请求参数赋值给user对象的对应属性
- springmvc把上述对象传入目标方法的参数
【注意】:在@ModelAttribute注解修饰的方法中,放入到map时的key需要和目标方法入参类型的第一个字母小写的字符串一致。若不一致,则password还是为null。解决方案是用@ModelAttribute注解
@ModelAttribute标记修饰目标方法POJO类型的入参
@ModelAttribute
public void getUser(@RequestParam(value="id", required=false) Integer id,
Map<String, Object> map) {
if(null != id) {
User u = new User();
...
map.put("u", u);
}
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("u") User user) {
System.out.println(user);
return SUCCESS;
}