处理模型数据

SpringMVC提供了以下几种途径输出模型数据:
ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据。
Map及Model:入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.util.map时,处理方法返回时,Map中的数据会自动添加到模型中。
@SessionAttributes:将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性。
@ModelAttribute:方法入参标注该注解后,入参的对象将会放到数据模型中。

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

	/**
	 * 目标方法返回类型可以是ModelAndView
	 * 其中可以包含视图和模型信息
	 * Spring MVC会把ModelAndView中model的数据放入到request域对象中
	 * @return
	 */
	@RequestMapping("testModelAndView")
	public ModelAndView testModelAndView() {
		
		ModelAndView model = new ModelAndView("success");
		model.addObject("time", new Date());
		return model;
	}
 

 在jsp页面使用${requestScope.time }获取

Map及Model:
SpringMVC在内部使用了一个org.springframework.ui.Model接口存储模型数据。
具体步骤
SpringMVC在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。如果方法的入参为Map或Model类型,Spring MVC会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据。
在这里插入图片描述

	/**
	 * 目标方法可以传入map,也可以是Model或者ModelMap类型的参数
	 * @param maps
	 * @return
	 */
	@RequestMapping("testMap")
	public String testMap(Map<String,Object> maps) {
		
		maps.put("names", Arrays.asList("zhangsan","lisi","wangwu"));
		return SUCCESS;
	}

@SessionAttributes(该注解只能放在类上,不能放在方法上)
如果希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中。@SessionAttributes除了可以通过属性名指定需要放到绘画中的属性外(通过注解中的value属性值设置),还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(通过注解中types属性值设置)。
@SessionAttributes(types = User.class)会将隐含模型中所有类型为User.class的属性添加到会话中。
@SessionAttributes(value= {“user1”,“user2”},types = User.class)


//在控制器上添加@SessionAttributes注解,下面注解表示模型中的names属性
//不仅会存放在Request作用域中,也会存放在Session中,User类型的属性也是一样
@SessionAttributes(value= {"names"},types = User.class)
 
 //必须是模型数据中存在的属性。
  	@RequestMapping("testMap")
	public String testMap(Map<String,Object> maps) {
		User user = new User();
		user.setUsername("zhangsan");
		user.setAge("20");
		maps.put("testUser", user);
		
		maps.put("names",Arrays.asList("wangwu","lisi"));
		return SUCCESS;
	}
 
 
 jsp页面中访问
 	request names,${requestScope.names }
	<br>
	request User,${requestScope.testUser }
	<br>
	<br>
	session names,${sessionScope.names }
	<br>
	session User,${sessionScope.testUser }

@ModelAttribute
有ModelAttribute标记的方法,会在每个目标方法执行之前被MVC调用,比如控制器类中定义了多个方法,且被@RequestMapping注解修饰,那么当访问方法时,被modelAttribute标记的方法会先执行。

	//在修改对象时,有些属性不想修改,例如对象的创建时间,密码等,但是如果界面上没有传入值,
 //那么在后台赋值的时候对应的属性会是null,如果执行更新操作,那么对应属性将会修改为null,所以可以使用
 //@ModelAttribute标注方法,让其从数据库中先查找数据,然后手动赋值界面传入的,再放入模型中,以供调用方法使用
 
     private static final String SUCCESS="success_test";

	@ModelAttribute
	private void getUser(@RequestParam(value="id",required = false)String id,Map<String,User> map) {
		
		if(id.equals("1")) {
			User user = new User();
			user.setUsername("test1");
			user.setAge("20");
			user.setPassword("123456");
			map.put("user", user);
			System.out.println("模拟从数据库中查找User :"+user.toString());
		}
		
	}
	
	@RequestMapping("/testModelAttribute")
	public String testModelAttribute(User user) {
		System.out.println("修改User : "+ user);
		return SUCCESS;
	}

上述代码运行流程:
执行@ModelAttribute注解修饰的方法:从数据库中取出对象,把对象放入map中,键为user
SpringMVC从map中取出user对象,并把表单的请求参数赋值给该user对象的对应属性
SpringMVC把上述对象传入目标方法的参数。

注意:在@ModelAttribute修饰的方法中,放入到Map时的键需要和目标方法入参类型的第一个字母小写的字符串一致,如上述代码map.put(“user”, user),而目标方法的入参类型为User。除了默认使用默认设置,也可以在目标方法参数中使用@ModelAttribute注解来映射,如下:map.put(“user111”, user),key为user111,在目标方法中使用@ModelAttribute(“user111”)来映射。

	@ModelAttribute
	private void getUser(@RequestParam(value="id",required = false)String id,Map<String,User> map) {
		
		if(id.equals("1")) {
			User user = new User();
			user.setUsername("test1");
			user.setAge("20");
			user.setPassword("123456");
			map.put("user111", user);
			System.out.println("模拟从数据库中查找User :"+user.toString());
		}
		
	}
	
	@RequestMapping("/testModelAttribute")
	public String testModelAttribute(@ModelAttribute("user111")User user) {
		System.out.println("修改User : "+ user);
		return SUCCESS;
	}

SpringMVC 确定目标方法POJO类型入参过程
确定一个Key
若目标方法的POJO类型参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写的名字。
若使用@ModelAttribute来修饰,则key为@ModelAttribute注解的value属性值。

在implicitModel中查找key对应的对象,若存在,则作为参数入参传入。(若使用了@ModelAttribute标记的方法中在Map中保存过,且key是上述描述中确定的key一致,就会获取到)

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

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

SpringMVC会把key 和POJO类型对象保存在implicitModel中,今儿会保存到Request中。

源码中:
1、调用@ModelAttribute注解修饰的方法,实际上把ModelAttribute方法中Map中的数据放在了implicitModel中。
2、解析请求处理器的目标参数,实际上该目标参数来自于WebDataBinder对象的target属性。
创建WebDataBinder对象;
确定ObjectName属性(若传入的attrName属性值为"",则objectName为类名第一个字母小写,注意:attrName,若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName 的值几位@ModelAttribute的value属性值,即上面代码所示);
确定target属性(在implicitModel中查找attrName对应的属性值,若不存在,则验证当前Handler是否使用率@SessionAttributes进行修饰,若使用了,则尝试从Session中获取attrName所对应的属性值。若Session中没有对应的属性值,则抛出异常,若Handler没有使用@SessionAttributes进行修饰,或@SessionAttributes中没有使用value值指定的key和attrName相匹配,则通过反射创建POJO类对象)
3、SpringMVC把表单的请求参数赋给了WebDataBinder的target对应的属性。
4、SpringMVC会把WebDataBinder的attrName和target给到implicitModel,从而传到Request域中。
5、把WebDataBinder的target作为参数传递给目标方法入参。

有@ModelAttribute标记的方法,会在每个目标方法执行之前被MVC调用。
@ModelAttribute注解也可以来修饰目标方法POJO类型的入参,其value属性值有如下作用
SpringMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参中。
SpringMVC会把value属性值作为key,POJO类型的对象作为value存入到Request中。如下目标方法中,会将user111作为key,User对象作为value存入Request域中,如果没有设置,则是默认为类名第一个字母小写的名字作为key,即user作为key.

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值