SpringMVC《源码剖析》2. 域对象获取和源码
本文最后更新于 2023-09-16,文章内容可能已经过时。
SpringMVC《源码剖析》2. 域对象获取和源码
域对象共享数据
只要关闭浏览器 ,session 真的就消失了?
不对。对 session 来说,除非程序通知服务器删除一个 session,否则服务器会一直保留,程序一般都是在用户做 log off 的时候发个指令去删除 session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id 就消失了,再次连接服务器时也就无法找到原来的 session。
如果服务器设置的 cookie 被保存在硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 session id 发送给服务器,则再次打开浏览器仍然能够打开原来的 session。 恰恰是由于关闭浏览器不会导致 session 被删除,迫使服务器为 session 设置了一个失效时间,当距离客户端上一次使用 session 的时间超过这个失效时间时,服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间。
总结:
观点:错误
1.除非程序通知服务器删除session,程序一般都是在用户做 log off 的时候发个指令去删除 session
2.大部分 session 机制都使用会话 cookie 来保存 session id
3.服务器为 session 设置了一个失效时间,当距离客户端上一次使用 session 的时间超过这个失效时间时,服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间。
1、使用ServletAPI向request域对象共享数据
2、使用ModelAndView向request域对象共享数据
这里我们如果方法返回ModelAndView,其实我们Thymeleaf视图解析需要获取字符串,然后前缀后缀拼接找对应位置静态资源然后渲染,所以返回这个,它需要能设置一个视图,这样DispatcherServlet解析视图给Thymeleaf就知道渲染哪个页面了。
3、使用Model向request域对象共享数据
这里不管是Model,ModelMap,可以去看源码,还有通过构造方法,等办法直接设置ModelAndView属性
4、使用map向request域对象共享数据
5、使用ModelMap向request域对象共享数据
6、Model、ModelMap、Map的关系
Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的。
Model是接口同时没有实现或继承任何类或接口,所以应该是springMVC中最底层的实现Model功能的接口。
而ModelMap是一个类,继承了LinkedHashMap,而LinkedHashMap必然继承了Map接口,他们本质都是靠实现类实现功能。
这里强烈建议温习的时候可以进入22尚硅谷的的springMVC教程的P42,看一下扒源码环节,加深内功和底层理解。
复杂参数:
- Map
- Model(map、model里面的数据会被放在request的请求域 request.setAttribute)
- Errors/BindingResult
- RedirectAttributes( 重定向携带数据)
- ServletResponse(response)
- SessionStatus
- UriComponentsBuilder
- ServletUriComponentsBuilder
用例:
Map<String,Object> map
Model model
HttpServletRequest request
上面三位都是可以给request域中放数据,用request.getAttribute()
获取
接下来我们看看,Map<String,Object> map
与Model model
用什么参数处理器。
Map<String,Object> map
参数用MapMethodProcessor
处理:
mavContainer.getModel()
如下:
Model model
用ModelMethodProcessor
处理:
return mavContainer.getModel();
这跟MapMethodProcessor
的一致
Model
也是另一种意义的Map
。
接下来看看Map<String,Object> map
与Model model
值是如何做到用request.getAttribute()
获取的。
众所周知,所有的数据都放在 ModelAndView 包含要去的页面地址View,还包含Model数据。
先看ModelAndView接下来是如何处理的?
在Debug模式下,view
属为InternalResourceView
类
exposeModelAsRequestAttributes
方法看出,Map<String,Object> map
,Model model
这两种类型数据可以给request域中放数据,用request.getAttribute()
获取。
7、请求处理-【源码分析】-自定义参数绑定原理
封装过程用到ServletModelAttributeMethodProcessor
先利用反射创建空实例attribute = createAttribute(name, parameter, binderFactory, webRequest);
内部用到web数据绑定器,将请求参数的值绑定到指定的JavaBean里面
WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中
在过程当中,用到GenericConversionService:在设置每一个值的时候,找它里面的所有converter那个可以将这个数据类型(request带来参数的字符串)转换到指定的类型
8、请求处理-【源码分析】-自定义Converter原理
未来我们可以给WebDataBinder里面放自己的Converter;
下面演示将字符串“啊猫,3”
转换成Pet
对象。
9、向session域共享数据
这里推荐用原生的方式,其实springMVC还提供了一个@SessionAttribute的注解
@SessionAttribute 是 Spring 框架中的注解之一,用于将请求中的参数绑定到会话的属性上。通常情况下,我们可以将该注解用于控制器类或处理器方法上。使用该注解可以方便地在会话中存储和访问数据,从而实现数据的持久化。在使用该注解时,需要注意会话属性的生命周期,以免出现意外的数据问题。
10、向application域共享数据
- 感谢你赐予我前进的力量