目录
一、Session的引入
1.什么是Session?
2.Session的基本原理 :
3.Session长什么样子?
二、Session的底层机制
1. Session接口相关的方法 :
1° req.getSession() :
2° httpSession.setAttribute(String name, Object val);
3° Object obj = httpSession.getAttribute(String name);
4° httpSession.removeAttribute(String name) :
5° isNew() :
6° getId() :
2.图解getSession()方法底层机制 :
3.JSESSIONID的抓包实例 :
1° 创建Session
2° 读取Session
三、Session生命周期
1.基本特征 :
2.细节 :
3.应用实例 :
(1) Session是服务器端技术,即Session数据保存在服务器端;服务器在运行时为每一个用户的浏览器创建一个其独享的session对象。
(2) 由于session对象为各个用户浏览器所独享,所以各个用户在访问服务器的不同页面时,可以从各自的session中读取/添加数据,实现自己操纵自己相关的数据。
(3) Session可以用于保存网络商场中的购物车信息,网站登录用户的信息等,也可以防止用户非法登录到某个页面。
示意图如下 :
1° 当用户打开浏览器,访问某个网站,操作session时,服务器就会在服务器端的内存中为该浏览器分配一个独有的session对象,该session对象被这个浏览器所独占。
2° session对象也可看做是一个容器/集合,session对象默认存在时间为 30min(服务器端)。(可通过tomcat安装目录下的conf/web.xml配置文件更改)
session是一种类似HashMap的容器,也存放(key-value键值对),每一行就是session 的一个属性。每个属性包含两个部分,前者是属性的名字(String类型),后者是属性的值(Object类型)。
如下图所示 :
HttpSession httpSession = req.getSession(); 该方法用于返回Session对象,实际是实现了Session接口的实现类对象。第一次调用该方法,是用于创建Session会话,之后调用是获取创建好的Session对象。
该方法用于向Session对象中添加属性。
Object obj = httpSession.getAttribute(String name); 也可以考虑多态的向下转型。该方法用于从Session对象中得到某个属性。
该方法用于从Session对象中删除掉某个属性。
该方法用于判断是不是刚创建出来的Session对象。
每个Session对象都有一个唯一标识的Id值,即JSESSIONID;通过getId()即可得到Session的会话Id值。
示意图如下 : (共三条线)
联系手写Tomcat底层机制中容器的实现机制。
CreateSessionServlet类代码如下 :
package bottom;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns={"/createSession"})
public class CreateSessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session对象(也可能是创建)
HttpSession httpSession = req.getSession();
System.out.println("httpSession = " + httpSession);
//获取Session对象的Id
String sessionId = httpSession.getId();
System.out.println("sessionId = " + sessionId);
//向Session容器中存放数据
httpSession.setAttribute("fruit", "Grape");
//回显
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print("Getting the session!
");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果如下(GIF):
ReadSessionServlet类代码如下 :
package bottom;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns={"/readSession"})
public class ReadSessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession httpSession = req.getSession();
System.out.println("Read's sessionId = " + httpSession.getId());
//传入name来获取Session属性
Object fruit = httpSession.getAttribute("fruit");
if (fruit != null) {
System.out.println("Session属性fruit = " + (String) fruit);
} else {
System.out.println("找不到\"name = fruit\"的session属性!");
}
resp.setContentType("html/text; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print("");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果如下GIF图 : (注意,先创建属性,再获取属性!)
1° public void setMaxInactiveInterval(int interval) : 设置Session的超时时间(以秒为单位),超过指定的时长,Session就会被销毁。
interval值为正数的时候,设定Session的超时时长。
interval值为负数的时候,表示Session永不超时.
2° public int getMaxInactiveInterval() : 获取Session的超时时间
3° public void invalidate() : 令当前的Session会话立即无效
4° 如果没有调用setMaxInactiveInterval()来指定Session的生命时长,Tomcat会以 Session默认时长为准,Session默认的超时为30分钟, 可以在tomcat的web.xml 设置
1° Session的生命周期指的是 :客户端 / 浏览器两次请求 最大间隔时长 ,而不是 累积时长 。 即当客户端访问了自己的session,session 的生命周期将从 0 开始 重新计算 ;即指的是 同一个会话两次请求之间的间隔时间。2° Tomcat 在底层会用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值, 则将该会话销毁。
CreateSession_EX类代码如下 :
package lifetime;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns={"/createEX"})
public class CreateSession_EX extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Session对象
HttpSession httpSession = req.getSession();
System.out.println("CreateEX's sessionId = " + httpSession.getId());
//设置Session对象的生命周期 = 30s
httpSession.setMaxInactiveInterval(20);
//设置Session对象的属性
httpSession.setAttribute("animal", "Cat");
//回显给浏览器
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print("创建Session!生命周期20s。
");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
ReadSession_EX类代码如下 :
package lifetime;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns={"/readEX"})
public class ReadSession_EX extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Session对象
HttpSession session = req.getSession();
System.out.println("ReadEX's sessionId = " + session.getId());
int maxInactiveInterval = session.getMaxInactiveInterval();
System.out.println("当前Session生命周期 = " + maxInactiveInterval);
//获取Session中的属性
Object animal = session.getAttribute("animal");
if (animal != null) {
System.out.println("animal = " + (String) animal);
} else {
System.out.println("原先的Session已经被销毁!");
}
//回显
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print("读取Session!
");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果 : (如下GIF)