1. Servlet 域对象
定义:可以在不同的 Servlet 中进行数据传递的对象就称为域对象。
Servlet 里面一共有四个域对象,四个域对象分别是page对象,request对象,session对象,application对象,用于在同一范围内的不同组件之间传递和共享数据。这些域对象使得数据能够在不同的请求处理过程中被访问和修改,从而支持多种 Web 应用的数据交互需求。
void setAttribute(String name, Object value); // 存储数据
Object getAttribute(String name); // 获取数据
void removeAttribute(String name); // 删除数据
//这三个方法是对域对象进行数据操作的三个方法,四个域对象作用范围从小到大是:
page < request < session < application
1.1 request (请求域)
对象名称:HttpServletRequest
request 对象代表一个请求,每次请求都是一个新的request对象。请求来时创建 request ,请求结束销毁 request。
业务场景:A资源通过转发的方式跳转到B资源,因为时转发的形式,所以A到B是一个请求,如果A资源和B资源想共享一个数据,那么需要将数据存储到 request 域中。
1.2 session (会话域)
对象名称:HttpSession
session 对象代表了一次会话,从浏览器打开访问到浏览器关闭,这是一个完整的会话。每个 session 对象都对应一个 JSESSIONID,而 JSESSIONID 以 cookie 存储在浏览器客户端中,浏览器关闭,JSESSIONID 失效,会话结束。
如果 session 超过30分钟没有使用,就会被销毁;如果服务器非正常关闭,没有到期的session也会跟着销毁;如果调用session提供的invalidate(),可以立即销毁session。
业务场景:
1.A资源通过重定向的方式跳转B资源,因为是重定向方式,A跳转B是两次请求,如果想让A和B资源共享同一个数据,可以将数据储存到 session 中。
2.登陆后保持用户状态。
1.3 application (应用)
对象名称:ServletContext
application 对象代表了整个 web 服务应用,服务器启动时创建,应用关闭时销毁。对于一个 web 应用来说,application 对象只有一个。
业务场景:记录网站的在线人数。
2. request 域对象
注意!注意!注意!:如果controller层需要通过thymeleaf去访问页面,注入MvcController的注解必须为@Controller,而不是@RestConreoller(@ResponseBody+@Controller)注解。
提前准备工作:
通过thymeleaf来作为试图展示效果,配置thymeleaf在SpringBoot中配置:
1. 先导入thymeleaf依赖
2. 配置文件内容:
Spring:
thymeleaf:
cache: false #不开启缓存
prefix: classpath:/templates/ #配置文件前缀
suffix: .html #配置文件后缀
mode: HTML #配置文件格式
encoding: UTF-8 #配置编码格式
servlet:
content-type: text/html
3. 添加页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Servlet 域</title>
</head>
<div id="bottom-text">
<h3> request 域对象效果展示 </h3>
<p th:text="${msg}"></p>
</div>
</body>
</html>
2.1 使用 Servlet API 方式
第一种方式:在 Spring MVC 中使用 Servlet API 可以完成 request 域数据共享。方式:在处理器方法上添加 HttpServletRequest 参数即可。
//伪代码
@RequestMapping(value = {"/servletAPI"})
public String toTestValue(HttpServletRequest request) {
//将共享的数据存储到 request 域中,设置k-v格式,可以在其他页面直接获取msg这个名称获取相对应的值
request.setAttribute("msg", "通过原生Servlet API 完成 request 域数据的共享");
//跳转视图,在视图页面将 request 域中的数据取出来,这样就完成了 controller 和 view 两个组件在同一个请求中数据共享
//这个跳转,默认是转发的方式: forward:
return "request";
}
2.2 使用 Model 接口
第二种方式:在 Spring MVC 中使用 Model 可以完成 request 域数据共享。方式:在处理器方法上添加 Model 参数即可。
@RequestMapping("/model")
public String model(Model model){
//将共享的数据存储到 request 域中,设置k-v格式,可以在其他页面直接获取msg这个名称获取相对应的值
model.addAttribute("msg","通过 model 来完成 request 域数据共享");
//转发
return "request";
}
2.3 使用 Map 接口
第三种方式:在 Spring MVC 中使用 Map 可以完成 request 域数据共享。方式:在处理器方法上添加 Map 参数即可。
@RequestMapping("/map")
public String model(Map<String,Object> map){
//将共享的数据存储到 request 域中,设置k-v格式,可以在其他页面直接获取msg这个名称获取相对应的值
map.put("msg","通过 Map 来完成 request 域数据共享");
return "request";
}
2.4 使用 ModelMap 类
第四种方式:在 Spring MVC 中使用 ModelMap 可以完成 request 域数据共享。方式:在处理器方法上添加 ModelMap 参数即可。
@RequestMapping("/modelMap")
public String model(ModelMap modelMap){
//将共享的数据存储到 request 域中,设置k-v格式,可以在其他页面直接获取msg这个名称获取相对应的值
modelMap.addAttribute("msg","通过 modelMap 来完成 request 域数据共享");
return "request";
}
2.5 使用 ModelAndView 类
第五种方式:在 Spring MVC 中使用 ModelAndView 可以完成 request 域数据共享。方式:在处理器方法中创建 ModelAndView 对象,并将数据添加到请求域中,并指定跳转视图名称即可。
/**
* 注意: 返回值必须是ModelAndView
* ModelAndView有Model和View的功能,Model主要用于向请求域共享数据,View主要用于设置视图,实现页面跳转
*/
@RequestMapping("/modelAndView")
public ModelAndView modelAndView(){
//创建 ModelAndView 对象
ModelAndView mav = new ModelAndView();
//绑定数据
mav.addObject("msg","通过 ModelAndView 来完成 request 域数据共享");
//设置跳转视图,实现页面跳转
mav.setViewName("request");
return mav;
}
2.6 Model、Map、ModelMap的关系
Model、modelMap、Map表面使用的是不同接口和不同的类,实际上底层都使用了同一个对象:org.springframework.validation.support.BindingAwareModelMap
BindingAwareModelMap 继承了 ExtendedModelMap 类
ExtendedModelMap 实现了 Model 接口
ExtendedModelMap 继承了 ModelMap 类
ModelMap 继承了 LinkedHashMap 类 继承了 HashMap 实现了 Map 接口
2.7 拓展
//对于处理器方法来说,不管你使用的参数是Model接口,还是Map接口,还是ModelMap类,还是创建ModelAndView类,最终处理器方法执行结束后,返回的都是ModelAndView对象,将这个对象交给DispatcherServlet类
//当请求路径不是JSP的时候,都会走DispatcherServlet(前端控制器)
//DispatcherServlet中有一个核心方法 doDispatch() 这个方法用来通过请求路径找到对应的处理器方法,然后调用处理器方法,处理器方法返回一个逻辑视图名称(也可能是ModelAndView对象),底层会将逻辑视图名称转为view对象,然后将model和view对象封装成一个ModelAndView对象,最后返回给DispatcherServlet
3. session 域对象
准备工作
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Servlet 域</title>
</head>
<div id="bottom-text">
<h3> session 域对象效果展示 </h3>
<!--在页面中就需要用session.key-->
<p th:text="${session.msg}"></p>
</div>
</body>
</html>
3.1 使用 Servlet API 方式
在处理器方法的参数上添加 HttpSession 参数,Spring MVC 会自动将 session 对象传递给这个参数。
@RequestMapping("/sessionA")
public String sessionA(HttpSession session){
//处理核心业务
//向 session 中绑定数据
session.setAttribute("msg","通过 Servlet API 方式共享 session 域对象数据!");
//返回逻辑视图名称
return "session";
}
3.2 使用 @SessionAttributes 注解
在处理器上使用 @SessionAttributes 注解绑定要共享到 session 域的数据。处理器方法中的参数model、map、modelMap都可以。
@Slf4j
@Controller
@RequestMapping("/mvc")
@SessionAttributes(value = {"msg"})
public class MvcController {
@RequestMapping("/sessionB")
public String sessionB(Model model){
//向会话中绑定数据
model.addAttribute("msg" ,"Spring mvc 使用@SessionAttributes 注解完成 session 域数据共享");
//返回视图名称
return "session";
}
}
4. application 域对象
application域是最大的域,作用在整个工程里面。application就是ServletContext,它的获取方法很多,可以通过request获取,也可以通过session获取。
准备工作
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Servlet 域</title>
</head>
<div id="bottom-text">
<h3> application 域对象效果展示 </h3>
<!--前端页面需要使用application.key-->
<p th:text="${application.msg}"></p>
</div>
</body>
</html>
使用 Servlet API 方式将数据共享到 application 域中,下面代码区别在于获取 application(ServletContext)对象的方式不同。
@RequestMapping("/applicationByRequest")
public String applicationA(HttpServletRequest request){ //通过request
//通过 request 获取 ServletContext,就是 application
ServletContext app = request.getServletContext();
//将数据存储到 application 中
app.setAttribute("msg", "在 SpingMVC 中通过 Servlet API 将数据共享到 application 域中");
return "application";
}
@RequestMapping("/applicationBySession")
public String applicationA(HttpSession session){ //通过session
//通过 session 获取 ServletContext,就是 application
ServletContext app =session.getServletContext();
app.setAttribute("msg", "在 SpingMVC 中通过 Servlet API 将数据共享到 application 域中");
return "application";
}