1.这个接口生成的对象是谁封装的?
1. 本质:它是一个接口
HttpServletRequest本身不是一个具体类,而是Servlet 规范(Java EE / Jakarta EE)定义的接口。你可以理解成:Java 制定了一个 “请求说明书”,规定必须有getParameter()、getSession()这些方法。
2. 真正的实现类:由Web 服务器封装
Tomcat、Jetty、Undertow、WebLogic 这些服务器,按照 Servlet 规范自己写了实现类。比如:
- Tomcat:
org.apache.catalina.connector.Request - Jetty:
org.eclipse.jetty.server.Request
3. 什么时候封装?
- 浏览器发送 HTTP 请求 → 到达服务器
- 服务器(Tomcat)接收 TCP 数据 → 解析 HTTP 协议
- 服务器自动创建 Request / Response 对象
- 传给过滤器 → 传给拦截器 → 传给 Controller
- 你在
preHandle里拿到的,就是服务器已经封装好的完整对象
2.request 对象里面到底有什么东西?
它把一次 HTTP 请求的所有信息全部封装好了,你直接调用方法就能拿。
主要包含 5 大类信息:
1.请求行信息
- 请求方法:GET / POST / PUT
- 请求 URL、URI
- 协议版本(HTTP/1.1)
request.getMethod(); // GET/POST request.getRequestURI(); // /api/user/login2.请求头信息
浏览器发过来的所有头:User-Agent、Cookie、Content-Type、Referer、Token 等
request.getHeader("User-Agent"); request.getHeader("token");3.请求参数
表单、URL 上的参数
request.getParameter("username"); request.getParameter("password");4.请求体(POST 数据)
JSON、表单数据、文件流
request.getInputStream(); request.getReader();5.请求相关上下文
- 客户端 IP
- 端口
- Session
- ServletContext
- 请求作用域(setAttribute)
3.Session 是不是被封装到 request 里了?
答案:是!而且是强关联!
1. 关系图解
浏览器 Cookie: JSESSIONID=xxxx ↓ 服务器收到请求 ↓ 服务器根据 JSESSIONID 找到对应的 Session ↓ 把 Session 关联到当前 Request 对象2. 你调用request.getSession()发生了什么?
- 从请求头 / Cookie 里拿
JSESSIONID - 服务器内存中查找对应会话
- 找到 → 返回已存在的 Session
- 没找到 →创建新 Session,并把 ID 写入 Cookie
3. 重要结论
- Session 不是存在 request 内部,而是服务器管理
- 但request 持有 session 的引用,你可以随时获取
- 一次请求 → 一个 request → 对应一个 session(如果有)
4.完整流程(极简版)
1. 第一次访问网站(无会话)
- 浏览器第一次请求服务端
- 请求头没有任何 JSESSIONID Cookie
- Tomcat 发现没会话 →自动新建一个 HttpSession 对象
- Tomcat 生成唯一 ID:
JSESSIONID=ABC123XYZ - 响应头带回
Set-Cookie,告诉浏览器:你下次访问我,带上这个 Cookie:JSESSIONID=ABC123XYZ
2. 第二次及后续访问(有会话)
- 浏览器记住了这个 Cookie
- 之后每一次请求,自动携带这条 Cookie 发给后端
- 后端拿到请求里的
JSESSIONID值 - 去服务器全局的 Session 池子中:
- 查到 → 复用旧的 Session 对象
- 查不到(过期 / 销毁)→ 新建 Session
5.一个浏览器只发送一个 cookie 然后再 session 中找到指定对象吗?
1. 浏览器会发多个 Cookie,但只靠 JSESSIONID 找 Session
- 浏览器可能存很多 Cookie(不同网站、不同业务)
- 但是只针对你这个后端项目域名,只会携带一条 JSESSIONID Cookie
- 服务端只认 JSESSIONID 这一个标识,别的 Cookie 不管
2. Session 存在哪里?
- Session 存在 服务器 (Tomcat) 内存中
- 全局一个 Session 映射容器:
Map<String, HttpSession> sessionMap key:JSESSIONID字符串 value:当前用户的Session对象- 本质就是:key-value 匹配
3. 一个浏览器 = 对应 一个 Session?
✅ 正常情况下:同一个浏览器、同一个标签页 / 网站域下 → 永远固定同一个 JSESSIONID → 同一个 Session
❌ 例外情况:
- 清除浏览器 Cookie
- 浏览器无痕模式
- Session 超时过期
- 后端手动
session.invalidate()→ 都会重新生成新的 JSESSIONID、新 Session
- Session 是服务端对象,Cookie 是浏览器本地存储
- JSESSIONID 是通行证,Cookie 只是用来传输这个通行证
- 就算你手动删了浏览器 JSESSIONID,服务端 Session 还在,只是没人能找到它了(慢慢超时销毁)
- 关闭浏览器:
- 浏览器临时 Cookie 消失
- 服务端 Session 不会立刻销毁,会等到超时(默认 30 分钟)
6.Session池子的创建
Session 池子(也就是HttpSession对象的集合)不是一启动就建好的空池子。
它是懒加载的。只有当你在代码里第一次调用request.getSession()时,它才会被创建。
一、什么时候创建?(关键:懒加载)
不是在服务器启动时!
- 服务器启动时:Tomcat 只初始化了
SessionManager(管理器),但内存里还是空的,没有任何 Session 池子。 - 第一次调用时:
- 你的代码调用
request.getSession(true)(默认也是 true)。 - 这时,Tomcat 才会临时创建一个
Map结构的 Session 容器(池子)。 - 然后在这个空池子里,新建一个
Session对象,分配唯一 ID,再放进去。
- 你的代码调用
二、具体是怎么创建的?(底层流程)
我们可以把这个过程想象成 “开柜台办卡” 的流程:
1. 触发点:request.getSession()
你在代码里调用这个方法,相当于告诉服务器:“我要找我的专属会话,没有就给我开一个!”
2. 第一步:找旧的(查池子)
- 服务器从
Request里取出JSESSIONID。 - 去全局的 Session 缓存(那个 Map 池子)里找:
Map<String, HttpSession> sessions - 如果找到了→ 直接把那个 Session 对象返回给你。
- 如果没找到(或者池子还没创建)→ 进入下一步。
3. 第二步:造新的(建池子 + 办卡)
这一步是核心,服务器会做三件事:
动作 A:创建容器(如果不存在)如果这是第一个用户访问,服务器还没有那个
sessionsMap,它会先在内存里创建一个空的 Map,这就是你的 “Session 池子”。动作 B:创建 Session 对象(新卡)服务器生成一个全新的
StandardSession对象(Tomcat 的默认实现)。- 给它分配一个唯一 ID:
JSESSIONID(比如8A7B6C5D...)。 - 记录创建时间、最后访问时间。
- 把它放入刚才创建的
sessionsMap 里(key 是 JSESSIONID)。
- 给它分配一个唯一 ID:
动作 C:响应给浏览器(写入 Cookie)为了让你下次还记得这个 ID,服务器会通过
Response响应头,给浏览器种下一个 Cookie:Set-Cookie: JSESSIONID=8A7B6C5D...; Path=/
4. 第三步:返回对象
最后,把你刚创建好的那个 Session 对象返回给你的代码,你就可以往里面setAttribute存数据了。
三、总结:Session 池子的本质
Session 池子本质上是一个ConcurrentHashMap(线程安全的 Map),它被挂载在ServletContext(整个应用)下。
- 创建时机:第一次调用
request.getSession()时。 - 创建过程:
- 检查 Map 存不存在 → 不存在就 new 一个(这就是池子)。
- 在 Map 里 put 新的 Session 对象。
四、一个有趣的冷知识
如果你在代码里从来没调用过request.getSession()或者request.getSession(true):
- 那么,Session 池子永远不会被创建。
- 服务器内存里就没有这个 Map,也不会消耗额外内存存 Session。
- 这就是为什么有些纯接口、无状态服务,可以做到极致节省资源的原因。
request.getSession(false):的时候就是只进行查询session对象不会创建session对象
以上由AI生成,有错误请指出,自己复习用