Spring MVC提供了四种方法来处理模型数据,分别如下。
===================
一、ModelAndView
处理方法返回值为ModelAndView时,方法即可通过该对象添加模型数据。
首先我们再页面中添加访问的超链接如下:
<a href="requestModelAndView">requestModelAndView</a>
然后在Controller中添加以下代码来对这个超链接作出反应:
@RequestMapping("/requestModelAndView")
public ModelAndView requestModelAndView(){
ModelAndView modelAndView=new ModelAndView("success");
modelAndView.addObject("user", new User("tom","12345",19));
return modelAndView;
}
因为前面设置了一个Resolver而这里的ModelAndView的名字success,所以会返回view/success.jsp文件,我们在这个文件中添加以下代码:
user:${requestScope.user}
然后运行之后可以看到点击第一个页面返回的页面内容如下:
user:User [username=tom, password=12345, address=null, age=19]
也就是打印出了信息,这就是ModelAndView的用法。
注意:一个ModelAndView对象包含了视图和模型信息,SpringMVC会把ModelAndView的model中的数据放入到requestScope中。
二、Map或Model
Map或Model入参(ModelMap类型也支持),也可以为访问的模型提供数据。
访问页面代码:
<a href="requestParamMap">requestParamMap</a>
请求处理代码:
@RequestMapping("/requestParamMap")
public String requestParamMap(Map<String, Object> params){
params.put("names", Arrays.asList("tom","jerry","dog"));
return "success";
}
返回页添加如下代码:
names:${requestScope.names}
这样便可以在点击请求也的超链接之后将数据反馈到返回页的代码之中了。
三、SessionAttributes注解
@SessionAttributes注解添加在控制器上边,Spring MVC会将其标注的变量名加入到HttpSession中,这也是让多个请求都能访问到模型数据的办法。
界面添加超链接如下:
<a href="requestSession">requestSession</a>
然后在处理类的上面添加一个注解,如下:
@SessionAttributes(value={"name"})
添加如下方法,方法中在map里面添加了一个键名为name的键值对:
@RequestMapping("/requestSession")
public String requestSession(Map<String, Object> map){
map.put("name", "tom");
return 'success';
}
然后再在返回的页面中查看两个结果,发现name已经添加到了两个域里面:
SessionScope name:${sessionScope.name}
<br>
requestScope name:${requestScope.name}
注意:这个注解必须添加到类上,并且注解除了可以修饰类型与变量名。
四、ModelAttribute
@ModelAttribute也是一个模型数据处理的注解,其主要的应用场景是数据库内容的变更,已知数据库中存在一个表单中,假如存在两种字段,一种是用户可见可修改的,一种是用户不可见的此时就会存在一种问题,我们在更新数据库时使用哪种逻辑。
Spring MVC提供了一种较为优雅的解决办法,以用户信息更改为例,一个用户的个人信息比如所在地,用户名这些一般可能是可见的字段,而密码这些一般是不可见字段。
所以当我们的用户要更改个人的一般信息时,会要求我们将整个数据从数据库中取出,以避免部分更改带来的多个SQL的编写。
Spring MVC带来的解决方法的具体代码如下。
更改信息的界面部分:
<form action="root/requestModelAttribute">
用户名:<input type="text" name="username"> <br>
年龄:<input type="text" name="age"> <br>
省份:<input type="text" name="address.province"> <br>
市:<input type="text" name="address.city"><br>
<input type="submit" value="提交">
</form>
User.java:
/**
*
* @author Sean
*
*/
public class User {
public User() {
}
public User(String username, String password, int age) {
super();
this.username = username;
this.password = password;
this.age = age;
}
private String username;
private String password;
private Address address;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", address=" + address + ", age=" + age + "]";
}
public void setPassword(String password) {
this.password = password;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Address.java:
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
@Override
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
}
public void setCity(String city) {
this.city = city;
}
}
然后在控制器中加入以下代码:
@ModelAttribute
public void getUser(Map<String,Object> map) {
// TODO Auto-generated method stub
//模拟查询数据库
User user=new User("aaa","qwer1234",19);
Address address=new Address();
address.setCity("city");
address.setProvince("pro");
user.setAddress(address);
System.out.println("修改后:"+user);
map.put("user", user);
}
@RequestMapping("/requestModelAttribute")
public String requestModelAttribute(User user){
System.out.println("修改后:"+user);
//指向seccess界面
return "seccess";
}
这样就完成了操作,我们会发现两个打印分别是:
修改前:User [username=aaa, password=qwer1234, address=Address [province=pro, city=city], age=19]
修改后:User [username=aaa, password=qwer1234, address=Address [province=ppp, city=ccc], age=22]
我们的界面中更改的属性不包括password 可以看到实际修改前后并没有修改password 这一属性,达到了我们部分更改数据条目的要求。
实际上@ModelAttribute修饰的方法会在所有的@RequestMapping修饰的方法之前运行。
上面这些代码中我们可以发现Spring MVC帮我们完成以下这么个流程。
- 执行@ModelAttribute修饰的方法:从数据库中取出对象把对象放入到map中
- 从map中取出对象并把表单请求的参数复制到对象中(请求中不包含的属性不进行更改)
- 把上述对象传递到@RequestMapping修饰的方法中
其实Spring MVC中所有@RequestMapping修饰的方法都会在@ModelAttribute修饰的方法之后执行,所以其他的对应的方法如果也需要相同的参数则应该注意一些点:
- map中加入对象的键的名字应该与后运行的方法中需要的类型名称的首字母小写一致。
- 如果不一致则需要对后运行的方法的参数列表中的参数用@ModelAttribute进行修饰,并且修饰的name值和map中的键值相一致