Session 及其使用示例
说明:下面介绍 Session,我们使用到了浏览器抓包,HTTP 的知识,如果不了解,请先简单了解下。HTTP 介绍,HTTP 请求,HTTP 响应。因为 Cookie 和 Session 是一对“好兄弟”,我们介绍 Session 也要使用到 Cookie,如果不清楚 Cookie,请查看 Cookie 详解。
什么是 Session
Session 在网络应用中称为“会话控制”,是服务器为了保存用户状态而创建的一个特殊的对象。简而言之,Session 就是一个对象,用于存储信息。
Session 有什么用
我们先来想一个问题,这个问题就是我们在游览购物网站时,我们并没有登录,但是我们任然可以将商品加入购物车,并且进行查看,当我们退出浏览器后再打开浏览器进行查看时,购物车中依然有我们选择的商品,这该怎么实现呢?
当然,我们可以使用 Cookie,但是 Cookie 不能存放大量数据,这时,我们就需要一种新的技术,Session。Session 是存储于服务器端的特殊对象,服务器会为每一个浏览器(客户端)创建一个唯一的 Session。这个 Session 是服务器端共享,每个浏览器(客户端)独享的。我们可以在 Session 存储数据,实现数据共享。
这是 Session 的简单原理示意图
![]() |
Session 类似于一个 Map,里面可以存放多个键值对,是以 key-value 进行存放的。key 必须是一个字符串,value 是一个对象。
Session 底层实现机制
Session 是每一个浏览器(客户端)所唯一的,这个是怎么实现的呢?其实,在访问一个网站时,在 HTTP 请求中往往会携带一个 Cookie,这个 Cookie 的名字是 JSESSIONID,这个 JSESSIONID 表示的就是 Session 的 id,这个是由服务器创建的,并且是唯一的。服务器在使用 Session 时,会根据 JSESSIONID 来进行不同操作,如下图所示:
![]() |
当我们在服务端使用 Session 时,首先要获取 Session,这个 Session 是通过 JSESSIONID 进行获取。当然,这时就已经有好多种情况了。例如浏览器访问时没有携带 JSESSIONID,浏览器携带的 JSESSIONID 对应的 Session 不存在(或者失效)等情况。上面这个图就对服务器获取 Session 的一些情况进行了说明。
浏览器抓包进行查看
下面我创建了一个简单的服务器,服务端操作 Session,看浏览器中的 JSESSIONID 是如何进行携带的。我服务器的访问地址是 localhost:8080/cs/createSession, 最开始浏览器是没有 JSESSIONID 的 Cookie,而服务端要操作 Session,我们访问后看服务器返回什么。
这是我们抓包后看到的请求头
![]() |
这是我们的响应头
![]() |
我们发现如果浏览器访问服务器,如果没有携带 JSESSIONID,那么服务器就会创建一个 Session,并且把这个 Session 的 JSESSIONID 返回给浏览器。
下面,我们再次访问同样的地址,这次就会携带 JSESSIONID 了。
我们发送的请求头
![]() |
我们抓包看见的响应头
![]() |
我们发现,如果浏览器携带了 JSESSIONID,那么浏览器在访问时就会携带。而服务器在使用 Session 时,就会使用这个 JSESSIONID 的 Session。
当然,上面是正常情况,那就是服务器端有对应 JSESSIONID 的 Session,并且没有过期。下面,我把浏览器发送请求的 JSESSIONID 改 2 个字母,看浏览器请求和服务器返回的是什么。
请求头
![]() |
响应头
![]() |
这次,我们发现请求头和响应头都携带了 JSESSIONID,这是因为浏览器携带的 JSESSIONID 在服务器端并没有对应的 Session,或者 Session 已经过期了。所以服务器创建了一个新的 Session,并且把新的 JSESSIONID 返回给了浏览器。
通过 Session 底层实现机制和 HTTP 抓包查看 JSESSIONID,大家应该已经对 Session 的原理有了清晰的认识。下面我来介绍一下 Session 的常用方法(基于 Java)。
Session 常用方法
- request.getSession():得到请求浏览器(客户端)对应的 Session。如果没有,那么就创建应该新的 Session。如果有那么就返回对应的 Session
- setAttribute(String s, Object o):在 Session 存放属性
- getAttribute(String s):从 Session 中得到 s 所对应的属性
- removeAttribute(String s):从 Session 中删除 s 对应的属性
- getId():得到 Session 所对应的 id
- invalidate():使 Session 立即无效
- setMaxInactiveInterval(int i):设置 Session 最大的有效时间。注意,这个有效时间是两次访问服务器所间隔的最大时间,如果超过最大的有效时间,那么这个 Session 就失效了。
Session 实例应用
我们利用 Session 来实现一个登录验证的功能。如果用户登录成功了,那么我们在 1 天内访问主页面就不需要登录了。我们利用 Session 进行实现。
我创建了一个 html 页面,2 个 servlet 来实现这次功能。代码如下:
html 页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> <base href="/cs/"> </head> <body> <form action="checkLogin" method="post"> 用户名:<input type="text" name="username" /><br/> 密 码:<input type="password" name="password" /><br/> <input type="submit" value="登录"> </form> </body> </html>
这个 html 就是一个简单的登录页面。
这个 Servlet 用于判断用户名和密码是否是我们规定的
import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/checkLogin") public class CheckServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //得到用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //判断用户名和密码是否为我们设置的密码 if (username.equals("tom") && password.equals("tom123")){ //得到 Session HttpSession Session = request.getSession(); //设置最长访问间隔时间 Session.setMaxInactiveInterval(60*60*24); //将用户名存入 Session Session.setAttribute("username",username); //重定向到主页面 response.sendRedirect(request.getContextPath()+"/mainPage"); }else { //设置 MIME 类型和编码 response.setContentType("text/html;charset=utf-8"); //写回提示信息 PrintWriter writer = response.getWriter(); writer.write("<h1>账号或密码错误</h1>"); writer.write("<h3><a href='"+request.getContextPath()+"/login.html'>点击重新登录</a></h3>"); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
这个 Servlet 就是我们的主页面
import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/mainPage") public class MainServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应的 MIME 类型和编码 response.setContentType("text/html;charset=utf-8"); //得到 Session HttpSession Session = request.getSession(); //取出用户名 Object username = Session.getAttribute("username"); PrintWriter writer = response.getWriter(); //判断用户名是否存在 if (username != null){ //在一天内登录过,无需再次登录 writer.write("<h1>用户:"+username+" 登录成功</h1>"); }else { //没有登录,或者登录间隔大于 1 天。重定向到登陆界面 response.sendRedirect(request.getContextPath()+"/login.html"); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
代码测试
我们一来就直接访问主界面。
![]() |
发现服务器发现我们没有登录,直接重定向到登录界面。下面我们来登录一下,输入我们设置的用户名和密码,分别是 tom 和 tom123
![]() |
我们登录成功了,那么现在我们关闭浏览器,然后重新打开,并且直接访问主界面,看能否直接访问。
![]() |
我们发现登录成功了,并没有重定向,因为我们已经登录过了嘛,一天之内都不需要重新登陆。我们的功能就实现了。
Session 和 Cookie 的比较
- Cookie 保存在客户端,Session 保存在服务端
- Cookie 作用于他所表示的 path 中(url 中要包含 path),范围较小。Session 代表客户端和服务器的一次会话过程,web 页面跳转时也可以共享数据,范围是本次会话,客户端关闭也不会消失。会持续到我们设置的 Session 生命周期结束(默认 30min)
- 我们使用 Session 需要 Cookie 的配合。Cookie 用来携带 JSESSIONID
- Cookie 存放的数据量较小,Session 可以存储更多的信息
- Cookie 由于存放在客服端,相对于 Session 更不安全
- 由于 Session 是存放于服务器的,当有很多客户端访问时,肯定会产生大量的 Session,这些 Session 会对服务端的性能造成影响
总结
Session 就是一个存储于服务器的特殊对象,通过 Session 可以实现数据共享,Session 有一个 JSESSIONID,这个是 Session 的唯一标识,使用它可以查找到 Session。Session 是会话级别的,对于每一个客户端来说是独享它所拥有的 Session 的,我们使用 Session 在进行页面跳转时,服务端可以利用 Session 进行数据共享。Session 由服务器进行控制。Session 的创建和销毁都是服务器进行管理的。服务器会为每一个客户端创建一个 Session。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端