学习参考 :
- 讲师:孙帅老师
- 课程:www.bilibili.com/video/BV1i5…
HttpServletRequest [简称request作用域]
用于组件间跳转时传递数据,比如控制器方法中传递数据给jsp页面
request.setAttribute("name","value");
在jsp中通过EL表达式获取 ${name}
HttpSession [简称session作用域]
用于用户会话追踪,只能存储与用户相关的个人数据, 如:登录状态、令牌、购物车等, (不用于传递数据)
session.setAttribute("name","value");
ServletContext [简称application作用域]
全局唯一,框架底层使用,多用于存储全局唯一的对象
如:Spring的工厂(容器)、Hibernate(JPA)的SessionFactory、MyBatis的SqlSessionFactory等
application.setAttribute("name","value");
上面的几种作用域,在使用中 都是依赖于servlet的api 实现的 setAttribute(),存在耦合性
在SpringMvc中 提供了其他方式去处理
Model 于 ModelMap 方式在作用域中传递对象
在方法形参中声明 Model或者是ModelMap,在方法中就可以使用 (解决的都是request作用域的传值)
@RequestMapping("/view2")
public String view2(Model model) {
model.addAttribute("name", "xiaojr");
return "redirect:/result1.jsp";
}
@RequestMapping("/view3")
public String view3(ModelMap modelMap) {
modelMap.addAttribute("name", "xiaowb");
return "result1";
}
对应在jsp页面中通过EL表达式获取 ${request.name}
Model和ModelMap 细节分析
- 上面的request作用域的处理,使用springMvc提供的方式替换了原有的传值方式
但是在底层,当springMvc发现页面我们使用的是jsp技术,还是会先将model或者modelMap中的数据放到 request中,(虽然底层还是使用request传值,但是这种写法避免了耦合)
当页面不是使用jsp技术的时候,springMvc会自动识别,选取合适的传值方式,但是不影响我们后端中这种写法
- model和modelMap的区别
通过代码可以看到两者在底层的时候对应的都是BindingAwareModelMap
- 那为什么不直接使用BindingAwareModelMap?
BindingAwareModelMap是springMvc的写法, 如果直接用BindingAwareModelMap去传递参数,相当于和springMvc耦合了,如果想要替换另一种控制器的开发方式 ,这时候没法替换
- 更推荐使用Model传值,因为Model是一个接口,在后续种有更好的兼容性
解决session作用域的问题
上面的方式都是解决request作用域的耦合性问题,springMvc也提供了解决session作用域传值的耦合性问题
@SessionAttributes 注解
下面的代码种,依旧是在model种添加了 name属性和值,如果没有@SessionAttributes 注解,那么这种方式传递的值,是在request种,但是加上了@SessionAttributes 注解,并且value种声明了要传递的key,这样就也完成了session作用域的存储数据 (并且可以传递多个值)
@Controller
@RequestMapping("/view3")
@SessionAttributes(value={"name"})
public class View3Controller {
@RequestMapping("/view1")
public String view1(Model model) {
model.addAttribute("name", "xiaojr");
return "result2";
}
}
这种方式下,request和session种都有name这个数据,存储的是同一个对象的引用
springMvc没有提供解耦ServletContext作用域的方法
因为上面几种方式,涉及到代码的耦合,都是指程序员开发种写的代码和servlet的api耦合了
但是ServletContext是全局的,多用于底层操作,而不需要程序员操作,所以也就没有提供对应的替换方法