ModelAndView的作用非常简单,就是两个作用。
第一个作用,往作用域中放值。
第二个作用,实现页面跳转。
15 - ModelAndView简单使用往request作用域中放值,有三种方式。
springmvc中提供了一个类,就是modelandview。model是模型。项目中的实体类,装载传输数据。view是视图,帮助我们设置视图,操作视图。
modelandview的构造器很多,如上图所示。
有参构造器当中的参数,说明modelandview的类当中,肯定是有对应的属性,肯定是有这些属性的set和get方法的。
model-and-view的add-object方法
我们看上图中的,第二个方法。
我们说过model-and-view当中的model是用来装载和传输数据的。
那么里面addObject方法,就是装载和传输数据的过程。
我们前面通过return "success"
这种方式,返回的就是视图名称。
现在我们通过modelAndView类
的setViewName
的方法,也可以设置视图名称。
所以,我们必须将ModelAndView对象,返回:
我们在request作用域中放了一个值,然后跳转到了success.jsp,然后我们就可以在success.jsp当中获取到request作用域中的值。
jsp当中jstl是c标签
el表达式是为了从作用域中取值,pagecontext,request,session,Application四个作用域。从小到大逐个作用域寻找。
我们可以加上作用域。
测试效果如下:
所以:modelandview的作用是装载数据,是往作用域中放置,view是设置视图名称,实现页面跳转。
16 - ModelAndView源码调试加载spring-webmvc的源码,查看ModelAndView里面的东西。
我们看一下:
- getModelInternal
- getModelMap
- getModel
- 这三个方法是一样的,都是获取model对象,model就是一个map,就是多个键值对数据。
debug - 断点
点击yes之后,进入到下面的视图:
调整视图布局,变成下面的样子:
- 双击打断点,debug模式启动项目,进入debug视图,在debug框框中,显示的是,执行到断点位置,已经调用的方法。
1、DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
- 上面的代码中有一个mv,这个mv就是ModelAndView。
- 我们的代码中,打断点的位置,是要返回一个ModelAndView对象。
- 这里的代码,意思就是通过ha.handle()方法,对请求进行了处理,获得了一个mv对象。
为什么是空的,因为这一行,还没有开始执行。断点所在的位置,是还没有执行的。
我们怎么从mv的代码的地方,走到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
的地方呢?
我们想要从mv的地方跑到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
的地方
- 第一,我们可以通过step over一步一步执行。
- 第二,我们可以在
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
位置,打一个断点,然后点击resume,就可以直接跳到我们需要的位置。
在这个位置,mv的值是,如下图所示:
2、进入processDispatchResult方法内部
进入方法内部,两种方式:
- 第一,按住ctrl键,鼠标点进去。
- 第二,step into。如果当前位置,有多个方法被调用,会按照方法执行的顺序,一个一个地进入。
我们在render(mv, request, response);
位置打一个断点,然后resume到render的位置,然后step into进去。
3、进入render方法内部
在这个render方法内部,已经把mv当中的view和model分开处理了。
在view.render(mv.getModelInternal(), request, response);
的位置,我们打一个断点,然后step into进入看看。
4、进入view.render()方法内部
view.render(mv.getModelInternal(), request, response);
这一行中有两个方法,render()
是一个方法,mv.getModelInternal()
也是一个方法。
我们点击step into之后,是mv.getModelInternal()
这个方法先执行。
第一次,step into,进入mv.getModelInternal()
方法内部。
第二次,step into,回到render方法的位置。
第三次,step into,这次是真正进入到render方法内部:
5、进入renderMergedOutputModel()方法内部
6、进入exposeModelAsRequestAttributes()方法内部
然后不断step over,从这个exposeModelAsRequestAttributes()
方法中出来。
7、回到renderMergedOutputModel()方法内部
ModelAndView的作用就是两个:第一往作用域中放值,第二实现页面跳转。
原来我们在servlet当中,往作用域中放值,和实现页面跳转,分别是这么写的。
request.setAttribute(key, value),往作用域中放值。
request.getRequestDispatcher.forward(),实现页面跳转
ModelAndView源码调试总结
17 - 三种方式实现作用域放值前面说过,往作用域中放值,是三种方式。
第一种方式
@RequestMapping(value="/param",method=RequestMethod.POST)
public ModelAndView param() {
ModelAndView mav = new ModelAndView();
mav.addObject("username", "root");
mav.setViewName("success");
return mav;
}
第二种方式
@RequestMapping(value="/param",method=RequestMethod.POST)
public String param(Map<String, Object> map) {
map.put("username", "admin");
return "success";
}
这种写法,默认也会将上面的map和return “success”包装成为ModelAndView对象的。
第三种方式
@RequestMapping(value="/param",method=RequestMethod.POST)
public String param(Model model) {
model.addAttribute("username", "zhangsan");
return "success";
}
通过model往作用域中放值,也会将model和"success"封装成为ModelAndView对象的
总结
springmvc处理请求过程中,往作用域中放值,有以下三种方式:
- map.put("username","admin")
- Model.addAttribute("username","admin")
- ModelAndView.addObject("username","admin")
上面三种写法,都会和view一起封装到ModelAndView中。
当前乱码问题
- 页面发送请求,传值
张三
- 我们在控制层的方法当中,接收了页面传值,看到控制台输出是乱码的:
- 作用域中放的值,页面显示是正常的。
为什么页面传值,控制层接收打印会乱码呢?
这是因为第一,页面传值的时候,默认会以页面的编码为编码格式。我们页面传过去的username默认是以utf-8编码的。
但是tomcat接收数据的时候,默认是用iso-8859-1来接收的。
springmvc为我们提供了一个编码过滤器,只要配置一下,就可以了。这个以后再说。
2019年6月17日 - day05 - 下午 - 结束