springMVC之处理模型数据

SpringMVC提供了以下几种途径输出模型数据:

·ModelAndView:处理方法返回值类型为ModeAndView时,方法体即可通过该对象添加模型数据

·Map及Model:入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.uti.Map时,处理方法返回时,Map中的数据会自动添加到模型中

·@SessionAttributes:将模型中某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性

·ModelAttribute:方法入参标注注解后,入参的对象就会放到数据模型中

ModelAndView

·控制器处理方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型信息。

·添加模型数据:

-ModelAndView addObject(String attributeName,Object attributeValue)

-ModelAndView addAllObject(Map<Stirng,?>modelMap)

·设置视图

-void setView(View view)

-void setViewName(String viewName)

SpringMVC.java

package com.f145a.springmvc.handlers;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
	
	private static final String SUCCESS="success";
	
	/**
	 * 目标方法的返回值可以是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

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="springmvc/testModelAndView">testModelAndView</a>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>成功页面!</h4>
time:${requestScope.time}
</body>
</html>

Map及Model

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

·具体步骤

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

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

SpringMVC.java

package com.f145a.springmvc.handlers;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
	
	private static final String SUCCESS="success";

	/**
	 * 目标方法可以添加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","Mike"));
		return SUCCESS;
	}
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="springmvc/testMap">testMap</a>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>成功页面!</h4>
<br>
names:${requestScope.names}
</body>
</html>

@SessionAttributes

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

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

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

-@SessionAttributes(value={“user1”,”user2”})

-@SessionAttributes(types={User.class,Dept.class})

-@SessionAttributes(value={“user1”,”user2”},types={Dept.class})

User.java

package com.f145a.springmvc.entities;

public class User {
	
	private String username;
	private String password;
	private String email;
	private int age;

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + ", email=" + email
				+ ", age=" + age + "]";
	}
	public User(String username, String password, String email, int age) {
		super();
		this.username = username;
		this.password = password;
		this.email = email;
		this.age = age;
	}
	
	public User(){
	
	}
}

SpringMVC.java

package com.f145a.springmvc.handlers;

import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.f145a.springmvc.entities.User;;

@SessionAttributes(value={"user"},types={String.class})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
	
	private static final String SUCCESS="success";

	/**
	 * @SessionAttributes除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是value属性值)
	 * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是types属性值)
	 * 注意:该注解只能放类上,而不可放方法上
	 * 
	 */
	@RequestMapping("/testSessionAttributes")
	public String testSessionAttributes(Map<String,Object> map){
		User user=new User("Tom","qwer","tom@qq.cpm",23);
		map.put("user", user);
		map.put("school", "beida");
		return SUCCESS;
	}
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="springmvc/testSessionAttributes">testSessionAttributes</a>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>成功页面!</h4>
<br>
request user:${requestScope.user}
<br>
session user:${sessionScope.user}
<br>
request school:${requestScope.school}
<br>
session school:${sessionScope.school}
</body>
</html>

ModelAttribute

User.java

package com.f145a.springmvc.entities;

public class User {
	
	private Integer id;
	private String username;
	private String password;
	private String email;
	private int age;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", age="
				+ age + "]";
	}
	
	public User(Integer id, String username, String password, String email, int age) {
	super();
	this.id = id;
	this.username = username;
	this.password = password;
	this.email = email;
	this.age = age;
    }
	public User(String username, String password, String email, int age) {
		super();
		this.username = username;
		this.password = password;
		this.email = email;
		this.age = age;
	}

	public User(){
	
	}
}

SpringMVC.java

package com.f145a.springmvc.handlers;

import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.f145a.springmvc.entities.User;;

@SessionAttributes(value={"user"},types={String.class})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
	
	private static final String SUCCESS="success";
	
	
	/**
	 * 1.有@ModelAttribute标记的方法,会在每个目标方法执行之前被SpringMVC调用!
	 * 2.@ModelAttribute注解也可以用来修饰目标方法POJO类型的入参,其属性值有如下的作用:
	 * >1.springMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参中
	 * >2.springMVC会以value为key,POJO类型对象为value,存入到request中
	 */
	@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",23);
			System.out.println("从数据库中获取一个对象:"+user);
			map.put("user", user);
		}
	}
	
	/**
	 * 运行流程:
	 * 1.执行@ModelAttribute注解修饰的方法:从数据库中取出对象,把对象放入到了Map中。键为:user
	 * 2.springMVC从Map中取出User对象,并把表单的请求参数赋给该User对象的对应属性
	 * 3.spring把上述对象传入目标方法的参数
	 * 注意:在@ModelAttribute修饰的方法中,放入到Map时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
	 * 
	 * springMVC确定目标方法POJO类型入参的过程
	 * 1.确定一个key
	 * >1.若目标方法的POJO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写
	 * >2.若使用了@ModelAttribute来修饰,则key为@ModelAttribute注解的value属性值
	 * 2.在implicitModel中查找key对应的对象,若存在,则作为入参传入
	 * >1。若在@ModelAttribute标记的方法在Map中保存过,且key和已确定的key一致,则会获取到
	 * 3.若impliciyModel中不存在key对应的对象,则检查当前的Handler是否使用@SessionAttributes注解修饰,
	 * 若使用了该注解,且@SessionAttributes注解的value属性值中包含了key,则会从HttpSession中来获取key所
	 * 对应的value值,若存在则直接传入到目标方法的入参中,若不存在则将抛出异常
	 * 4.若Handler没有标示@SessionAttributes注解或@SessionAttributes注解的value值中不包含key,则
	 * 会通过反射来创建POJO类型的参数,传入为目标方法的参数
	 * 5.springMVC会把key和POJO类型的对象保存到implicitModel中,进而会保存到request中
	 * 
	 * 源代码分析的流程
	 * 1.调用@ModelAttribute注解修饰的方法,实际上把@ModelAttribute方法中Map中的数据放在了implicitModel中,
	 * 2.解析请求处理器的目标参数,实际上该目标参数来自WebDataBinder对象的target属性
	 * >1.创建WebDataBinder对象:
	 * (1)确定objectName属性:若传入的attrName属性值为"",则objectName为类名第一个字母小写
	 * 注意:attrName,若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName值即为@ModelAttribute的value属性值
	 * (2)确定target属性:
	 * >在implicitModel中查找attrName对应的属性值,若存在,OK;*若不存在:则验证当前Handler是否使用了@SessionAttribute进行
	 * 修饰,若使用了,则尝试从Session中获取AttrName所对应的属性值,若session中没有对应的属性值,则抛出异常;若Handler没有使用
	 * @SessionAttribute进行修饰,或@SessionAttribute中没有使用value值指定的key和attrName相匹配,则通过反射创建POJO对象
	 * >2.springMVC把表单的请求参数赋给了WebDataBinder的target对应的属性
	 * >3.*springMVC会把WebDataBinder的attrName和target给implicitModel,进而传给request域对象中
	 * >4.把WebDataBingder的target作为参数传递给目标方法的入参
	 */
	@RequestMapping("/testModelAttribute")
	public String testModelAttribute(User user){
		System.out.println("修改:"+user);
		return SUCCESS;
	}
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 模拟修改操作
	1.原始数据为:1,Tom,123456,tom@qq.com,23	
	2.密码不能被修改
	3.表单回显,模拟操作直接在表单填写对应的属性值
 -->
<form action="springmvc/testModelAttribute" method="post">
	<input type="hidden" name="id" value="1" />
	<br>
	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="age" value="23"/>
	<br>
	<input type="submit" value="submit">
</form>
</body>
</html>

欢迎访问我的个人博客http://www.chengzequn.top

转载于:https://my.oschina.net/chengzequn/blog/782264

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值