MVC 数据处理模型

数据处理模型

Spring MVC 执行流程

Spring MVC 的执行流程中,控制层(Controller 层)在调用 Service 层处理之后,会有一个返回结果。在原生的 JavaEE 中,对于返回结果,可以使用 request.getAttribute() 或者 session.setAttribute() 来把信息保存到 session 域和 request 域,那么在 SpringMVC 中,它是如何把数据保存到这两个域 ? 这里就要借助 Spring 提供的数据模型 ModelAndView ,ModelMap 等等。

ModelAndView

请求处理器的目标方法的返回值,如果为 ModelAndView ,它既是包含了视图(View),也包含了数据模型(Model)。它是由 Spring 提供的,可以把返回的界面信息都保存到这个 ModelAndView 返回出去。

添加数据模型的方法

  • addObject(String,Object)
    • 添加单个数据,第一个参数为数据模型的名称,第二个参数就是数据模型(像 request.setAttribute() 一样)
  • addAllObject(Map<String,Object>)
    • 表示将键值对的所有数据都加入到数据模型,map 的 key 也就是数据模型名称,value 就是数据模型

添加视图方法

  • setView(View view)
    • 设置视图
  • setViewName(String viewName)
    • 设置视图名称

实例代码:

	@RequestMapping("testModelAndView")
	public ModelAndView testModelAndView() {
		ModelAndView modelAndView = new ModelAndView();
        //添加视图信息
		modelAndView.setViewName("success.jsp");
        //添加数据模型
		modelAndView.addObject("name1","小王");
		return modelAndView;
	}

上面代码也就是,把数据模型 “小王” 放入到 modelAndView 中,而 视图是 success.jsp,那么当这个目标方法执行之后,则会跳转到 success.jsp 界面,并且在 request 域中获得 name1 属性值。

success.jsp

<body>
	<h1>成功了</h1>
	<h1>name1 : ${name1}</h1>
</body>

所以,总结一下

  • ModelAndView 中的数据模型 会被SpringMVC自动的放入到请求域
  • ModelAndView 中的视图信息会被SpringMVC的视图解析器解析,并进行转发

源码分析

我们在 return modeAndView 打断点。进入到 DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) 的方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	 .....

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;
		...
				// 执行目标方法 testModelAndView.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			.....
	}

可以看的返回值,为一个 ModelAndView,所以无论返回值是什么,或者入参。Spring 会封装成一个 ModelAndView 返回出来。

Map、Model、ModelMap

对于这三个数据模型,如果在处理器目标方法的入参为这三个数据模型,最终会被 SpringMVC 处理。并且放入到 ModelAndView 的模型中

可以看的 ModelAndView 的几个构造函数中,能够把上面的三种类型都装入进行,或者 setXXX 方法也可以。也就是说,在 入参中,书写上面的三种模型,最后也是被转为 ModelAndView,并且最终加入请求域。

例子

	@RequestMapping("testModel")
	public String  testModel(Model model) {
		model.addAttribute("name2", "我是 model");
		
		return "success";
	}
	
	@RequestMapping("testModelMap")
	public String testModelMap(ModelMap modelMap) {
		 
		modelMap.addAttribute("name3","我是 modelmap");
		
		return "success";
	}
	
	@RequestMapping("testMap")
	public String testModelMap(Map map) {
		 
		map.put("name4", "我是 map");
		
		return "success";
	}

那么三者又是什么关系

Model,ModelMap与Map是同类的,在方法上只是方法名的不同,而处理的方式相同的。

@SessionAttributes 注解

上面说完了 放入请求域,那么如何放入 session 域?Spring MVC 提供了 @SessionAttributes 注解,可以将 SessionAttributes 加入到 session 域中。

该注解只能注解到类上。它有两种写法,一种针对类型,一种针对数据模型名称。

针对数据模型名称

@Controller
@RequestMapping("demo")
@SessionAttributes(value="name")
public class TestController {
	@RequestMapping("testMap")
	public String testModelMap(Map map) {
		map.put("name", "我是 session");
		return "success.jsp";
	}
}

上面的代码意思是,把数据模型名称为 name 的加入到 request 域,并且加入到 session 域。接下来,在 success.jsp 界面就可以用 sessionScope 获取

<h2>name : ${sessionScope.name}</h2>

针对类型

@Controller
@RequestMapping("demo")
@SessionAttributes(types=Admin.class)
public class TestController {
	@RequestMapping("testMap")
	public String testModelMap(Map map) {
		Admin admin = new Admin();
		admin.setAccount("11111");
		admin.setPassword("12345678");
		map.put("admin", admin); 
		return "success.jsp";
	}
}

上面的代码意思是,把数据模型的类为 Admin.class 的加入到 request 域,并且加入到 session 域。接下来,在 success.jsp 界面就可以用 sessionScope.admin.account 获取

同时,你可以把两种写法写到一起。

@Controller
@RequestMapping("demo")
@SessionAttributes(value="name",types=Admin.class)
public class TestController {
	@RequestMapping("testMap")
	public String testModelMap(Map map) {
		Admin admin = new Admin();
		admin.setAccount("11111");
		admin.setPassword("12345678");
		map.put("admin", admin); 
		return "success.jsp";
	}
}

意思就是上面两个结合起来了。

扩展

@SessionAttributes注解引发的异常

如果有@SessionAttribute注解,而且存在@ModelAttribute注解的方法,而且处理器的目标方法的入参类型存在于@SessionAttribute注解的types属性中,而且@ModelAttribute注解的方法没有将此类型的对象加入到请求域中,那么会报异常。我们得分析流程:

  1. 执行@ModelAttribute注解的方法
  2. 执行目标方法,目标方法入参存在Student
  3. 目标方法到请求域中寻找@ModelAttribute注解方法加入到请求域中的Student
  4. 寻找不到,则看类中是否存在@SessionAttribute,并且注解的types中有Student类型,如果有Student类型,则到Session域中寻找student,寻找不到,报错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值